uniapp快速开发小程序全流程

news2024/10/7 8:19:55

uniapp快速开发小程序全流程

完整项目代码:https://gitee.com/Zifasdfa/ziyi-app

欢迎fork与star

1 项目效果及环境准备

1.1 项目效果

本文主要使用uniapp实现一个简单的app应用

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.2 环境准备&项目初始化

①node环境:去node.js官网下载稳定版的node即可,下载之后配置环境变量,通过node -v查看是否配置成功

在这里插入图片描述

② 开发工具选择:HBuilder-X

官网下载地址:https://uniapp.dcloud.net.cn/quickstart.html#

根据自己的操作系统下载对应的环境即可,下载好之后,双击.exe文件打开HBuilderX

点击左上角:文件 - 新建项目 - 选择uni-app项目,填写对应项目名,其他默认即可【这里我采用vue2的语法】

效果:
在这里插入图片描述

展示效果选择手机页面方式:

在这里插入图片描述
当然我们也可以通过数据线,将手机与电脑连接起来,然后直接在真机上运行。
在这里插入图片描述

2 实现tabbar底部导航

增加底部导航,为:首页、分类、学习、我的

官网tabbar教程:https://uniapp.dcloud.net.cn/collocation/pages.html#tabbar

  • tabBar 中的 list 是一个数组,只能配置最少2个、最多5个 tab,tab 按数组的顺序排序。

①导入图片资源

导入所给源码中的static下的图片

在这里插入图片描述

②新建tabbar目录及对应页面

因为我们整个项目是将底部导航栏中的index默认为首页,因此删除之前pages目录的index整个文件夹,并在pages下新建tabbar目录,然后在tabbar目录下分别新建classify、index、mine、study页面

在这里插入图片描述

③修改页面主题颜色,修改App.vue

<style>
	/*每个页面公共css 修改页面主背景色为灰色,配合白色的底部导航栏*/
	body{
		background-color: #f8f8f8;
	}
</style>

④配置底部导航栏,修改package.json

  • 配置页面

在pages配置下,修改页面配置,包括修改页面路径及是否允许下拉刷新等

{
	"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
		{
			//指定有哪些页面,并配置样式
		    "path" : "pages/tabbar/index/index",
		    "style" :                                                                                    
		    {
				//页面顶部的文本
		       "navigationBarTitleText":"首页",
			   "navigationStyle":"custom"
		    }
		    
		}
		,{
		    "path" : "pages/tabbar/classify/classify",
		    "style" :                                                                                    
		    {
				"navigationBarTitleText":"分类",
				"navigationBarBackgroundColor":"#00b783",
				"navigationBarTextStyle":"white",
				//不启动下拉刷新
				"enablePullDownRefresh":false
		    }
		    
		}
		,{
		    "path" : "pages/tabbar/study/study",
		    "style" :                                                                                    
		    {
		    	"navigationBarTitleText":"学习中心",
		    	"navigationBarBackgroundColor":"#00b783",
		    	"navigationBarTextStyle":"white",
		    	"enablePullDownRefresh":false
		    }
		    
		}
		,{
		    "path" : "pages/tabbar/mine/mine",
		    "style" :                                                                                    
		    {
		    	"navigationBarTitleText":"个人中心",
		    	"navigationBarBackgroundColor":"#00b783",
		    	"navigationBarTextStyle":"white",
		    	"enablePullDownRefresh":false
		    }
		    
		}
    ],
	...
}
  • 新增tabbar配置

包括配置文本,选中未选中时候的图标等

{
	"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
	....
	
	// 底部导航栏
	"tabBar":{
		"color":"#999",
		//选中时的颜色
		"selectedColor":"#00b783",
		"borderStyle":"white",
		"backgroundColor":"#FFFFFF",
		"list":[
			{
				//底部导航栏的index对应页面
				"pagePath":"pages/tabbar/index/index",
				//对应文本
				"text":"首页",
				//未选中时的图标
				"iconPath":"static/tabar1.png",
				//选中之后的图标
				"selectedIconPath":"static/tabaron1.png"
			},
			{
				"pagePath":"pages/tabbar/classify/classify",
				"text":"分类",
				"iconPath":"static/tabar2.png",
				"selectedIconPath":"static/tabaron2.png"
			},
			{
				"pagePath":"pages/tabbar/study/study",
				"text":"学习",
				"iconPath":"static/tabar3.png",
				"selectedIconPath":"static/tabaron3.png"
			},
			{
				"pagePath":"pages/tabbar/mine/mine",
				"text":"我的",
				"iconPath":"static/tabar4.png",
				"selectedIconPath":"static/tabaron4.png"
			}
		]
	}
}

⑤查看效果

然后重新运行在浏览器,如果显示不出效果,则先暂停,然后重新运行在对应浏览器

在这里插入图片描述

效果:

在这里插入图片描述

3 实现搜索框(使用第三方组件实现)

①下载第三方组件

组件 - 自定义导航栏-下载组件

在这里插入图片描述
选择下载并导入:
在这里插入图片描述

注意,下载插件是需要注册账号并登录的,如果没有账号的话,注册并登录即可

导入成功之后的效果:
在这里插入图片描述

②安装scss/sass插件

因为我们后续会使用到css中的scss语法,所以需要提前安装插件

工具 - 插件安装
在这里插入图片描述

如果已经存在则无需安装

否则,点击安装新插件,插件市场中搜索sass,然后选择下载插件并导入
在这里插入图片描述

③抽取nav-bar组件(防止主页面代码过多不易维护)

在components组件下新建navbar目录,然后在navbar目录下创建navbar.vue文件

在这里插入图片描述
navbar.vue:

<template>
	<view>
		<view class="example-body">
			<!--uni-nav-bar 中的 statusBar 主要是为了适配"齐刘海",防止navbar遮盖住手机顶部的电量、时间等状态 -->
			<uni-nav-bar shadow statusBar :fixed="false" color="#333333" background-color="#FFFFFF" right-icon="scan">
				<view class="input-view">
					<uni-icons class="input-uni-icon" type="search" size="22" color="#666666" />
					<input confirm-type="search" class="nav-bar-input" type="text" placeholder="输入搜索关键词">
				</view>
			</uni-nav-bar>
		</view>
	</view>
</template>

<script>
	import uniNavBar from '@/components/uni-nav-bar/uni-nav-bar.vue'
	export default {
		data() {
			return {

			}
		},
		methods: {

		},
		components: {
			uniNavBar
		}
	}
</script>

<style lang="scss">
	.input-view {
		/* #ifndef APP-PLUS-NVUE */
		display: flex;
		/* #endif */
		flex-direction: row;
		width: 600rpx;
		flex: 1;
		background-color: #f8f8f8;
		height: 30px;
		border-radius: 15px;
		padding: 0 15px;
		flex-wrap: nowrap;
		margin: 7px 0;
		line-height: 30px;
	}

	.input-uni-icon {
		line-height: 30px;
	}

	.nav-bar-input {
		height: 30px;
		line-height: 30px;
		/* #ifdef APP-PLUS-NVUE */
		width: 370rpx;
		/* #endif */
		padding: 0 5px;
		font-size: 28rpx;
		background-color: #f8f8f8;
	}

	.example-body {
		padding: 0;
	}
</style>

④在pages/tabbar/index/index.vue中引入Navbar组件

<template>
	<view>
		<!-- 引入顶部搜索框导航栏 -->
		<Navbar/>
		
	</view>
</template>

<script>
	import Navbar from "../../../components/navbar/navbar.vue"
	export default {
		data() {
			return {
				
			}
		},
		methods: {
			
		},
		components:{
			Navbar,
		}
	}
</script>

⑤效果

页面效果:
在这里插入图片描述

4 首页实现Banner轮播图

通过网络请求动态获取图片数据

4.1 通过网络请求获取数据

uni.request发起网络请求
pages/tabbar/index/index.vue:

<script>
	import Navbar from "../../../components/navbar/navbar.vue"
	export default {
		data() {
			return {
				//多张图片,用数组存放
				topBanner: [],
				
			}
		},
		methods: {
			
		},
		mounted(){
				//vue的生命周期函数
				uni.request({
					url: "http://html5.bjsxt.cn/api/index/banner",
					//注意:网络请求必须要按照下面的方式发起,不能使用新语法等
					success: (res) => {
						// console.log(res)
						this.topBanner = res.data.top_banner
					}
				})
		},
		components:{
			Navbar,
		}
	}
</script>

②通过console.log打印网络请求所返回的数据:
在这里插入图片描述
③根据网络返回的结果获取图片

需要根据自己的手机型号进行样式的调整

pages/tabbar/index/index.vue:

<template>
	<view class="home">
		<!-- 引入顶部搜索框导航栏 -->
		<Navbar/>
		<view class="index_banner_box">
			<!-- 顶部banner,同时配置对应参数 -->
			<swiper class="swiper" :indicator-dots="true" :autoplay="true" :interval="3000" :duration="500">
				<!-- 从图片数组中取出对应图片并展示在页面上 -->
				<swiper-item v-for="(item, index) in topBanner" :key="index">
					<image class="banner" :src="item.img_url" mode=""></image>
				</swiper-item>
			</swiper>
		</view>
	</view>
</template>

<script>
	...
</script>

<!-- 使用scss的语法 -->
<style lang="scss">
	.home {
		//flex:盒子模型
		display: flex;
		flex-direction: column;
		flex: 1;
		overflow: hidden;
		.index_banner_box {
			display: flex;
			width: 100%;
			padding: 10px;
			justify-content: center;
			align-items: center;
			border-radius: 5px;
			overflow: hidden;
			.swiper{
				width: 100%;
				height: 260rpx;
				.banner{
					width: 700rpx;
					height: 260rpx;
				}
			}
		}
	}
</style>

4.2 在页面中展示图片数据并配置样式

4.3 结果

在这里插入图片描述

5 实现课程导航

注意:import用于在js中引入css文件, @import用于在css中引入css文件

5.1 抽取课程导航coursenav为component,并编写页面

①引入源码中common下的图标样式,css文件等

在这里插入图片描述
②在components文件夹下新建coursenav
在这里插入图片描述
coursenav.vue:

<template>
	<view class="course_nav_con">
		<view class="course_nav_info" v-for="(item, index) in list" :key="index">
			<text class="course_nav_icon icon iconfont" :class="item.icon"></text>
			<view class="course_info_text">{{item.text}}</view>
		</view>
		
	</view>
</template>

<script>
	export default {
		data() {
			return {
				list: []
			}
		},
		mounted() {
			uni.request({
				url: "http://html5.bjsxt.cn/api/index/nav",
				success: (res) => {
					this.list = res.data.data
				}
			})
		},
		methods: {
			
		}
	}
</script>

<style lang="scss">
	
	// import用于在js中引入css文件, @import用于在css中引入css文件
	@import "@/common/font/iconfont.css";

	.course_nav_con {
		display: flex;
		// 盒子模型不撑开容器本身大小
		box-sizing: border-box;
		flex-direction: row;
		flex-wrap: wrap;
		padding: 15px 10px;

		.course_nav_info {
			width: 20%;
			flex-direction: row;
			flex-wrap: wrap;
			text-align: center;
			margin-bottom: 15px;

			.course_nav_icon {
				font-size: 30px;
			}

			.icon-java {
				color: #2a83fe;
			}

			.icon-weifuwu {
				color: #fd3761;
			}

			.icon-zuzhijiagou {
				color: #2b91e2;
			}

			.icon-dashuju {
				color: #2a83fe;
			}

			.icon-h {
				color: #00b478;
			}

			.icon-icon-- {
				color: #fd6012;
			}

			.icon-rengongzhineng {
				color: #fe391f;
			}

			.icon-ruanjianceshi {
				color: #00b478;
			}

			.icon-huatong {
				color: #fea917;
			}

			.icon-bianchengshibaobiao_icon {
				color: #2a83fe;
			}

			.icon-jianmo {
				color: #00b478;
			}

			.icon-chuangye {
				color: #fe391f;
			}

			.course_info_text {
				width: 100%;
				font-size: 13px;
				margin-top: 10px;
				white-space: nowrap;
				text-overflow: ellipsis;
				overflow: hidden;
			}
		}
	}
</style>

5.2 主页导入课程

在pages/tabbar/index/index.vue中引入CourseNar

  • import CourseNav from “…/…/…/components/coursenav/coursenav.vue”
  • components中添加CourseNav,
  • template标签中添加<CourseNav/>
<template>
	<view class="home">
		<!-- 引入顶部搜索框导航栏 -->
		<Navbar/>
		<view class="index_banner_box">
			<!-- 顶部banner,同时配置对应参数 -->
			<swiper class="swiper" :indicator-dots="true" :autoplay="true" :interval="3000" :duration="500">
				<!-- 从图片数组中取出对应图片并展示在页面上 -->
				<swiper-item v-for="(item, index) in topBanner" :key="index">
					<image class="banner" :src="item.img_url" mode=""></image>
				</swiper-item>
			</swiper>
		</view>
		<!-- 课程导航栏 -->
		<CourseNav/>
	</view>
</template>

<script>
	import Navbar from "../../../components/navbar/navbar.vue"
	import CourseNav from "../../../components/coursenav/coursenav.vue"
	export default {
		data() {
			return {
				//多张图片,用数组存放
				topBanner: [],
				
			}
		},
		methods: {
			
		},
		mounted(){
				//vue的生命周期函数
				uni.request({
					url: "http://html5.bjsxt.cn/api/index/banner",
					//注意:网络请求必须要按照下面的方式发起,不能使用新语法等
					success: (res) => {
						// console.log(res)
						this.topBanner = res.data.top_banner
					}
				})
		},
		components:{
			Navbar,
			CourseNav,
		}
	}
</script>

5.3 效果

部分网络上的css及图标样式已经获取不到了,所以大家可以替换新的网络地址来获取对应的图标

在这里插入图片描述

6 实现限时免费

6.1 创建free-card的components

新建free-card目录,然后新建free-card.vue文件

在这里插入图片描述

<template>
	<view>
		<view class="free_card_box" v-for="(item, index) in teaList" :key="index">
			<!-- 老师图片 -->
			<view class="free_card_img">
				<image :src="item.teacher_logo" mode=""></image>
			</view>
			<!-- 限时免费文本信息 -->
			<view class="free_card_txt">
				<view class="free_card_T">{{ item.limitName }}</view>
				<view class="free_card_info">
					<view class="free_card_info_txt">
						<view class="info_txt1">{{ item.teacher_name }}{{ item.teacher_job }}</view>
						<view>{{ item.limitNum }}人学过</view>
					</view>
					<view class="free_card_info_btn" v-if="item.baoming == '马上报名'">{{ item.baoming }}</view>
					<view class="free_card_info_btn free_card_info_btn1" v-else>{{ item.baoming }}</view>
				</view>
			</view>
		</view>
	</view>
</template>

<script>
	export default {
		name:"free-card",
		data() {
			return {
				teaList:[]
			}
		},
		mounted(){
			uni.request({
				url:"http://html5.bjsxt.cn/api/index/specific?userid=2162",
				success: (res) => {
					this.teaList = res.data.data
				}
			})
		},
		methods: {
			
		}
	}
</script>

<!-- .free_card_box的class里面再点.free_card_img的class 为 scss语法 -->
<style lang="scss">
	.free_card_box{
		display: flex;
		padding: 10px 0;
		margin: 10px;
		border-radius: 10px;
		box-shadow: 0 0  5px 1px rgba($color: #000000, $alpha: 0.1);
		box-sizing: border-box;
		align-items: center;
		margin-bottom: 15px;
		background-color: #fff;
		.free_card_img{
			flex-shrink: 0;
			width: 91rpx;
			height: 91rpx;
			border-radius: 100%;
			margin: 0 15px;
			image{
				width: 100%;
				height: 100%;
				border-radius: 100%;
			}
		}
		.free_card_txt{
			width: 100%;
			display: flex;
			box-sizing: border-box;
			flex-direction: column;
			padding: 0 15px 0 0;
			.free_card_T{
				font-size: 16px;
				white-space: nowrap;
				text-overflow: ellipsis;
				overflow: hidden;
				margin: 10px 0;
			}
			.free_card_info{
				width: 100%;
				display: flex;
				box-sizing: border-box;
				flex-flow: row nowrap;
				justify-content: space-between;
				.free_card_info_txt{
					width: 60%;
					overflow: hidden;
					font-size: 16px;
					color: #666;
					.info_txt1{
						height: 20px;
						font-size:14px;
						overflow: hidden;
					}
				}
				.free_card_info_btn{
					width: 100px;
					height: 34px;
					text-align: center;
					line-height: 34px;
					border-radius: 34px;
					background-color: #00b783;
					color: #fff;
					font-size: 16px;
					margin-top: 10px;
				}
				.free_card_info_btn1{
					background-color: #ddd;
				}
			}
		}
	}
</style>

6.2 首页引入free-card

  1. 在script标签中导入
  2. 在component中导入
  3. 在页面中引用

修改pages/tabbar/index/index.vue
①在课程导航栏下方添加FreeCard组件及在线课程图标

		<!-- 课程导航栏 -->
		<CourseNav/>
		<!-- 在线课程图标 -->
		<view class="online_box">
			<image :src="index_banner.img_url" class="online_img"></image>
		</view>
		<view class="free_box">
			<view class="free_T_box public_tow_box">
				<view class="public_T">
					限时免费
				</view>
			</view>
			<FreeCard />
		</view>

②在script中获取图片和文本数据,并引入FreeCard组件

<script>
	import Navbar from "../../../components/navbar/navbar.vue"
	import CourseNav from "../../../components/coursenav/coursenav.vue"
	import FreeCard from "../../../components/free-card/free-card.vue"
	export default {
		data() {
			return {
				//多张图片,用数组存放
				topBanner: [],
				index_banner:{},
			}
		},
		methods: {
			
		},
		mounted(){
				//vue的生命周期函数
				uni.request({
					url: "http://html5.bjsxt.cn/api/index/banner",
					//注意:网络请求必须要按照下面的方式发起,不能使用新语法等
					success: (res) => {
						// console.log(res)
						this.topBanner = res.data.top_banner
						this.index_banner = res.data.index_banner
					}
				})
		},
		components:{
			Navbar,
			CourseNav,
			FreeCard, //引入限时免费组件
		}
	}
</script>

③在style中新增css样式

<!-- 使用scss的语法 -->
<style lang="scss">
	.home {
		//flex:盒子模型
		display: flex;
		flex-direction: column;
		flex: 1;
		overflow: hidden;
		.index_banner_box {
			display: flex;
			width: 100%;
			padding: 10px;
			justify-content: center;
			align-items: center;
			border-radius: 5px;
			overflow: hidden;
			.swiper{
				width: 100%;
				height: 260rpx;
				.banner{
					width: 700rpx;
					height: 260rpx;
				}
			}
		}
		.online_box{
			display: flex;
			width: 724rpx;
			justify-content: center;
			align-items: center;
			box-sizing: border-box;
			overflow: hidden;
			margin-bottom: 15px;
			
			.online_img{
				//1px 约等于2 rpx
				width: 724rpx;
				height: 132rpx;
			}
			
		}
		.public_tow_box{
			display: flex;
			width: 100%;
			justify-content: center;
			align-items: center;
			box-sizing: border-box;
			overflow: hidden;
			padding: 0 15px;
			justify-content: space-between;
			align-content: space-between;
			flex-wrap: wrap;
			.public_T{
				font-size: 20px;
				font-weight: 700;
			}
		}
		.public_title{
			width: 100%;
			display: flex;
			padding: 0 15px;
			flex-direction: column;
			.public_class_t{
				font-size: 22px;
				font-weight: 700;
				margin-bottom: 15px;
			}
		}
	}
</style>

6.4 效果

在这里插入图片描述

7 实现就业班模块

view标签与div标签区别:

  • view标签通常具有更丰富的功能,比如数据绑定、事件处理等。而div标签只是一个简单的容器,没有特定的功能。

7.1 创建jobScroll

步骤与前面大同小异

在这里插入图片描述

<template>
	<!-- 就业班模块:根据接口返回数据拼装内容 -->
	<view class="job_scroll_box">
		<scroll-view scroll-x="true" class="job_scroll_con_box">
			<view class="job_scroll_con">
				<view class="job_scroll_info" v-for="(item,index) in list" :key="index">
					<view class="job_scroll_card" :class="item.colors">
						<view class="job_scroll_card_T">{{ item.textT }}</view>
						<view class="job_scroll_card_icon">
							<view class="icon iconfont" :class="item.icon"></view>
						</view>
						<view class="job_scroll_card_des">{{ item.text }}</view>
						<view class="job_scroll_card_btn">免费试学</view>
					</view>
				</view>
			</view>
		</scroll-view>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				list: []
			}
		},
		mounted() {
			uni.request({
				url: "http://html5.bjsxt.cn/api/index/course",
				success: (res) => {
					this.list = res.data.data
				}
			})
		},
		methods: {

		}
	}
</script>

<style lang="scss">
	// @import :从css中引入css
	@import "@/common/font/iconfont.css";

	.job_scroll_box {
		width: 100%;
		margin-bottom: 30px;
		box-sizing: border-box;

		.job_scroll_con {
			display: flex;
			align-items: center; //垂直据中
			flex-wrap: nowrap; //不换行
			box-sizing: border-box;

			.job_scroll_info {
				width: 225px;
				height: 260px;
				flex-shrink: 0;
				margin: 0 10px;

				.job_scroll_card {
					display: flex;
					flex-flow: column;
					box-sizing: border-box;
					align-items: center; //水平据中
					width: 100%;
					height: 248px;
					background-color: #b0def5;
					border-radius: 5px;
					margin-top: 12px;

					.job_scroll_card_T {
						display: flex;
						align-items: center; //水平据中
						justify-content: center; //垂直居中
						width: 210px;
						height: 38px;
						background-color: #e4f3fb;
						font-size: 16px;
						text-align: center;
						margin-top: -15px;
						border-bottom-left-radius: 25px;
						border-bottom-right-radius: 25px;
						border-top-left-radius: 15px;
						border-top-right-radius: 15px;
					}

					.job_scroll_card_icon {
						display: flex;
						align-items: center; //水平据中
						justify-content: center; //垂直居中
						box-sizing: border-box;
						width: 90px;
						height: 90px;
						background-color: #d3ecf9;
						border-radius: 100%;
						margin: 20px 0 15px;

						view {
							font-size: 42px;
							color: #2a83fe;
						}

					}

					.job_scroll_card_des {
						display: flex;
						box-sizing: border-box;
						align-items: center; //水平据中
						font-size: 14px;
					}

					.job_scroll_card_btn {
						display: flex;
						box-sizing: border-box;
						align-items: center;
						justify-content: center; //垂直居中
						width: 118px;
						height: 32px;
						line-height: 32px;
						color: #0a5ea0;
						font-size: 16px;
						border-radius: 34px;
						border: 1px solid #0a5ea0;
						margin-top: 15px;
					}
				}

				.job_scroll_card2 {
					background-color: #fed2b0;

					.job_scroll_card_T {
						background-color: #fff2e7;
					}

					.job_scroll_card_icon {
						background-color: #fee6d3;

						view {
							color: #d87e4e;
						}
					}

					.job_scroll_card_btn {
						color: #c44606;
						border: 1px solid #c44606;
					}
				}

				.job_scroll_card3 {
					background-color: #fee4b7;

					.job_scroll_card_T {
						background-color: #fef4e2;
					}

					.job_scroll_card_icon {
						background-color: #fef0d7;

						view {
							color: #b17001;
						}
					}

					.job_scroll_card_btn {
						color: #b17001;
						border: 1px solid #b17001;
					}
				}

				.job_scroll_card4 {
					background-color: #f5bcf7;

					.job_scroll_card_T {
						background-color: #fae0fb;
					}

					.job_scroll_card_icon {
						background-color: #f9d9fa;

						view {
							color: #8f0494;
						}
					}

					.job_scroll_card_btn {
						color: #8f0494;
						border: 1px solid #8f0494;
					}
				}

				.job_scroll_card5 {
					background-color: #cff2cb;

					.job_scroll_card_T {
						background-color: #ebf9e9;
					}

					.job_scroll_card_icon {
						background-color: #e4f7e2;

						view {
							color: #138a06;
						}
					}

					.job_scroll_card_btn {
						color: #138a06;
						border: 1px solid #138a06;
					}
				}

				.job_scroll_card6 {
					background-color: #f9cbc8;

					.job_scroll_card_T {
						background-color: #fce8e6;
					}

					.job_scroll_card_icon {
						background-color: #fbe2e0;

						view {
							color: #980c03;
						}
					}

					.job_scroll_card_btn {
						color: #980c03;
						border: 1px solid #980c03;
					}
				}

				.job_scroll_card7 {
					background-color: #f3eaa3;

					.job_scroll_card_T {
						background-color: #f8f3cc;
					}

					.job_scroll_card_icon {
						background-color: #f8f3cc;

						view {
							color: #786b03;
						}
					}

					.job_scroll_card_btn {
						color: #786b03;
						border: 1px solid #786b03;
					}
				}

				.job_scroll_card8 {
					background-color: #b4eef3;

					.job_scroll_card_T {
						background-color: #e4f9fb;
					}

					.job_scroll_card_icon {
						background-color: #d5f5f8;

						view {
							color: #088691;
						}
					}

					.job_scroll_card_btn {
						color: #088691;
						border: 1px solid #088691;
					}
				}

				.job_scroll_card9 {
					background-color: #f7c8a4;

					.job_scroll_card_T {
						background-color: #fcebdd;
					}

					.job_scroll_card_icon {
						background-color: #fae0cc;

						view {
							color: #9c4604;
						}
					}

					.job_scroll_card_btn {
						color: #9c4604;
						border: 1px solid #9c4604;
					}
				}

				.job_scroll_card10 {
					background-color: #cfd2fe;

					.job_scroll_card_T {
						background-color: #edefff;
					}

					.job_scroll_card_icon {
						background-color: #e4e6fe;

						view {
							color: #4e06ab;
						}
					}

					.job_scroll_card_btn {
						color: #4e06ab;
						border: 1px solid #4e06ab;
					}
				}
			}
		}
	}
</style>

7.2 首页中引入

pages/tabbar/index/index.vue:

		<!-- view标签功能更强大:表示一个视图 -->
		<view class="public_title">
			<view class="public_class_t">零基础就业班</view>
			<JobScroll />
		</view>

其他和前面类似,导入JobScroll组件,然后在页面中引用即可

7.3 效果

在这里插入图片描述

8 实现课程推荐部分

8.1 新增course-card这个component

<template>
	<view class="course_card_box">
		<view class="course_card_con">
			<view class="course_card_info" v-for="(item,index) in list" :key="index">
				<view class="course_card_img">
					<image :src="item.logo" mode=""></image>
				</view>
				<view class="course_card_des">
					<view class="course_card_des_T">{{ item.textT }}</view>
					<view class="course_card_des_info">
						<view class="course_card_des_pay">¥{{item.money}}</view>
						<view class="course_card_des_icon">
							<text class="icon iconfont icon-yonghu2"></text>
							{{item.hits}}人学过
						</view>
					</view>
				</view>
			</view>
		</view>
	</view>
</template>

<script>
	export default {
		data(){
			return{
				list:[]
			}
		},
		mounted(){
			uni.request({
				url:"http://html5.bjsxt.cn/api/index/recommend",
				success: (res) => {
					this.list = res.data.data
				}
			})
		}
	}
	
</script>

<style lang="scss">
	@import '@/common/font/iconfont.css';

	.course_card_box {
		width: 100%;
		display: flex;
		box-sizing: border-box;
		padding: 0 15px;
		margin-bottom: 15px;
		overflow: hidden;
		align-items: center;
		justify-content: center;

		.course_card_info {
			display: flex;
			box-sizing: border-box;
			width: 100%;
			background: #fff;
			border-radius: 15px;
			padding: 10px;
			margin-bottom: 15px;
			flex-direction: row;
			align-items: center; //子元素垂直居中

			.course_card_img {
				flex-shrink: 0;
				margin-right: 15px;

				image {
					width: 240rpx;
					height: 140rpx;
				}
			}

			.course_card_des {
				width: 100%;
				display: flex;
				box-sizing: border-box;
				flex-direction: column;

				.course_card_des_T {
					font-size: 16px;
					line-height: 24px;
					margin-bottom: 5px;
				}

				.course_card_des_info {
					width: 100%;
					display: flex;
					flex-direction: row; //横向排列
					box-sizing: border-box;
					justify-content: space-between;
					/* 横向中间自动空间 */
					align-content: space-between;
					/* 竖向中间自动空间 */
					flex-wrap: wrap;

					/* 换行 */
					.course_card_des_pay {
						font-size: 12px;
						color: #ff5200;

						text {
							font-size: 16px;
						}
					}

					.course_card_des_icon {
						font-size: 14px;
						color: #333;

						text {
							font-size: 14px;
							color: #666;
							margin: 0 2px 0 0;
						}
					}
				}
			}
		}
	}
</style>

8.2 首页引入

<template>
	<view class="home">
 	...
		<!-- view标签功能更强大:表示一个视图 -->
		<view class="public_title">
			<view class="public_class_t">零基础就业班</view>
			<JobScroll />
		</view>
		<view class="recommend_box">
			<view class="recommed_T_box public_tow_box">
				<view class="public_T">推荐课程</view>
			</view>
			<CourseCard />
		</view>
		<view class="daotu_box">
			<view class="daotu_T">驱动教学-贯穿教|学|练|测|评</view>
			<image :src="fontBanner.img_url" mode=""></image>
		</view>
	</view>
</template>
<script>
	import Navbar from "../../../components/navbar/navbar.vue"
	import CourseNav from "../../../components/coursenav/coursenav.vue"
	import FreeCard from "../../../components/free-card/free-card.vue"
	import JobScroll from "../../../components/jobscroll/jobscroll.vue"
	import CourseCard from "../../../components/course_card/course_card.vue"
	export default {
		data() {
			return {
				//多张图片,用数组存放
				topBanner: [],
				index_banner:{},
				fontBanner:{}
			}
		},
		methods: {
			
		},
		mounted(){
				//vue的生命周期函数
				uni.request({
					url: "http://html5.bjsxt.cn/api/index/banner",
					//注意:网络请求必须要按照下面的方式发起,不能使用新语法等
					success: (res) => {
						// console.log(res)
						this.topBanner = res.data.top_banner
						this.index_banner = res.data.index_banner
						this.fontBanner = res.data.foot_banner
					}
				})
		},
		components:{
			Navbar,
			CourseNav,
			FreeCard, //引入限时免费组件
			JobScroll,
			CourseCard
		}
	}
</script>

8.3 效果

在这里插入图片描述

9 课程列表详情、课程介绍详情实现

9.1 新建courseIntroduce页面

①新建courseIntroduce目录及页面
在这里插入图片描述

②修改pages.json

//在"pages"配置下新增courseIntroduce配置
        ,{
            "path" : "pages/course/courseIntroduce/courseIntroduce",
            "style" :                                                                                    
            {
                "navigationBarTitleText": "课程介绍",
				"navigationBarBackgroundColor":"#0c9c8f",
				"navigationBarTextStyle":"white",
                "enablePullDownRefresh": false
            }
        }

9.2 给coursenav.vue新增点击事件

		//template部分:新增点击事件
		<view class="course_nav_info" v-for="(item, index) in list" :key="index" @click="courseItemHandle(item.id,item.course)">
			<text class="course_nav_icon icon iconfont" :class="item.icon"></text>
			<view class="course_info_text">{{item.text}}</view>
		</view>
		
		...
<script>
		...
		methods: {
			// 点击事件,点击图标跳转页面,并传入id和course
			courseItemHandle(id, course){
				uni.navigateTo({
					// url为pages中配置的courseIntroduce配置的页面路径,同时将id和course传过去
					url:"/pages/couser/courseIntroduce/courseIntroduce?id=" + id +"&course="+course
				})
			}
		}
</script>

9.3 新增course-jieshao、courseList、courseIntroduce-data component

在这里插入图片描述

course-jieshao.vue:

<template>
	<view class="course_jieshao_box">
		<image :src="images" mode="" :style="{ height:imageHeight + 'rpx' }"></image>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				
			}
		},
		props:{
			images:{
				type:String,
				defualt:""
			},
			imageHeight:{
				type:String,
				default:""
			}
		},
		methods: {
			
		}
	}
</script>

<style lang="scss">
	.course_jieshao_box{
		display: flex;
		box-sizing: box;
		flex-direction: column;
		justify-content: center;
		width: 100%;
		image{
			width: 750rpx;
			
		}
	}
</style>

courseList.vue:

<template>
	<view class="course_list_box">
		<view class="course_list_con">
			<view class="course_list_info" @click="clickViode" v-for="(item,index) in videoList" :key="index">
				<view class=".course_list_info_txt">{{ item.type_name }}</view>
			</view>
		</view>
	</view>
</template>

<script>
	export default {
		data() {
			return {

			}
		},
		props: {
			videoList: {
				type: Array,
				default: function() {
					return []
				}
			}
		},
		methods: {
			clickViode(){
				uni.navigateTo({
					url:"/pages/couser/video/video"
				})
			}
		}
	}
</script>

<style lang="scss">
	.course_list_box {
		display: flex;
		box-sizing: border-box;
		flex-direction: column;
		width: 100%;
		padding: 0 15px;

		.course_list_con {
			display: flex;
			box-sizing: border-box;
			flex-direction: column;
			flex-grow: 1;

			.course_list_info {
				display: flex;
				box-sizing: border-box;
				flex-direction: center;
				overflow: hidden;
				flex: 1;
				width: 100%;
				height: 45px;
				line-height: 45px;
				font-size: 14px;
				border-bottom: 1px solid #efefef;

				.course_list_info_txt {
					white-space: nowrap;
					overflow: hidden;
					text-overflow: ellipsis;
				}
			}
		}
	}
</style>

courseIntroduce-data.vue

<template>
	<view class="courseIntroduce_data_box">
		<view class="courseIntroduce_data_info" v-for="(item,index) in msg" :key="index">
			<view class="courseIntroduce_data_txt1"><text>{{ item.num }}</text></view>
			<view class="courseIntroduce_data_txt2"><text>{{ item.txt }}</text></view>
		</view>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				
			}
		},
		props:{
			msg:{
				type:Array,
				default:function(){
					return []
				}
			}
		},
		methods: {
			
		}
	}
</script>

<style lang="scss">
	.courseIntroduce_data_box {
		display: flex;
		box-sizing: border-box;
		flex-direction: row;
		/*横向排列*/
		flex-wrap: wrap;
		/* 换行排列 */
		justify-content: center;
		/*居中对齐*/
		width: 100%;
		padding: 15px 10px;

		.courseIntroduce_data_info {
			display: flex;
			box-sizing: box;
			flex-direction: column;
			justify-content: center;
			align-items: center;
			width: 25%;
			height: 80px;
			flex-grow: 1;
			position: relative;

			.courseIntroduce_data_txt1 {
				text-align: center;
				width: 100%;
				font-size: 12px;
				color: #ff5200;
				overflow: hidden;
				white-space: nowrap;
				text-overflow: ellipsis;
				margin-bottom: 10px;

				text {
					font-size: 16px;
				}
			}

			.courseIntroduce_data_txt2 {
				text-align: center;
				width: 100%;
				font-size: 13px;
				color: #333;
				overflow: hidden;
				white-space: nowrap;
				text-overflow: ellipsis;
			}
		}

	}
</style>

9.4 courseIntroduce页面中引入course-jieshao、courseList、courseIntroduce-data组件

courseIntroduce.vue:

<template>
	<view class="home">
		<view class="courseIntroduce_box">
			<view class="courseIntroduce_des">
				<view class="courseIntroduce_info">{{ introduce }}</view>
			</view>
			<CourseIintroduceData :msg="introduceList"/>
			<view class="question_line"></view>
			<view class="courseIntroduce_tab_box">
				<view class="courseIntroduce_tab_nav">
					<view v-for="(item,index) in items" :class="{ 'btna':count === index }" @tap="change(index)" :key="index">{{ item }}</view>
				</view>
				<view class="courseIntroduce_tab_con">
					<view class="discount_info" :class="{dis:count === 0}">
						<CourseList :videoList="Clist"/>
					</view>
					<view class="discount_info" :class="{dis:count === 1}">
						<CourseJieshao :images="imageT" :imageHeight="imageHeight"/>
					</view>
				</view>
			</view>
		</view>
	</view>
</template>

<script>
	
	import CourseIintroduceData from "../../../components/courseIntroduce-data/courseIntroduce-data.vue"
	import CourseList from "../../../components/courseList/courseList.vue"
	import CourseJieshao from "../../../components/course-jieshao/course-jieshao.vue"
	export default {
		data() {
			return {
				introduce:"",
				introduceList:[],
				items:["课程章节","课程介绍"],
				count:0,
				Clist:[],
				imageT:"",
				imageHeight:""
			}
		},
		components:{
			CourseIintroduceData,
			CourseList,
			CourseJieshao
		},
		onLoad(options) {
			uni.request({
				url: "https://www.itbaizhan.cn/api/course/detail",
				// 参数
				data: {
					id: options.id,
					course: options.course
				},
				success: (res) => {
					this.introduce = res.data.data.introduce
					this.introduceList = res.data.data.introduceList
					this.Clist = res.data.data.Clist
					this.imageT = res.data.data.image
					this.imageHeight = res.data.data.height
				}
			})
		},
		methods: {
			change(index){
				this.count = index;
			}
		}
	}
</script>
<style lang="scss">
	.courseIntroduce_box {
		display: flex;
		box-sizing: box;
		flex-direction: column;
		margin-bottom: 90px;

		.courseIntroduce_des {
			display: flex;
			box-sizing: border-box;
			flex-direction: column;
			justify-content: center;
			align-items: center;
			width: 100%;
			background-color: #0c9c8f;
			padding: 0 10px 15px;
			overflow: hidden;

			.courseIntroduce_info {
				display: flex;
				box-sizing: box;
				width: 100%;
				color: #fff;
				font-size: 16px;
				line-height: 24px;
			}
		}

		//tab
		.courseIntroduce_tab_box {
			display: flex;
			box-sizing: border-box;
			flex-direction: column;

			.courseIntroduce_tab_nav {
				display: flex;
				box-sizing: border-box;
				flex-direction: row;
				background-color: #fff;
				border-bottom: 1px solid #e4e4e4;
				margin-bottom: 20px;

				view {
					height: 50px;
					line-height: 50px;
					font-size: 16px;
					flex-grow: 1;
					text-align: center;
					background-color: #fff;

				}
			}

			.discount_info {
				display: none;
			}

			.btna {
				display: flex;
				box-sizing: border-box;
				justify-content: center; //水平方向对齐
				color: #00b783;
				position: relative;
			}

			.btna::after {
				content: '';
				width: 40px;
				height: 3px;
				background-color:#00b783;
				position: absolute;
				bottom: 0;
				left: 50%;
				margin-left: -20px;
			}

			.dis {
				display: block;
			}
		}
	}
</style>

9.5 效果

在这里插入图片描述

10 播放页面实现(webView)

web-view:在浏览器中内嵌网页,可以理解为一个内嵌的浏览器

10.1 创建video页面

在这里插入图片描述
video.vue:

<template>
	<view>
		<!-- 后期根据课程详情页面跳转时传过来的数据,请求后端或者拼接对应视频地址替换即可 -->
		<web-view src="https://www.bilibili.com/video/BV1ZM4y177kh/"></web-view>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				
			}
		},
		methods: {
			
		}
	}
</script>

<style>

</style>

10.2 给courseList添加点击事件跳转视频播放

courseList.vue:

<template>
	<view class="course_list_box">
		<view class="course_list_con">
			<view class="course_list_info" @click="clickViode" v-for="(item,index) in videoList" :key="index">
				<view class=".course_list_info_txt">{{ item.type_name }}</view>
			</view>
		</view>
	</view>
</template>
<script>
		methods: {
			clickViode(){
				uni.navigateTo({
					// 跳转视频播放页面
					url:"/pages/course/video/video"
				})
			}
		}
	}
</script>

10.3 效果

在这里插入图片描述

bug

如果运行项目发现报错:‘core-js/modules/es.string.iterator.js’

  • 则表明缺少core-js环境,在终端cmd执行下面命令
# 安装core-js之后,重新启动项目
npm i core-js -D

11 打包发布项目

11.1 app打包

①在manifest.json中配置AppID、图标等,如果没有AppID则重新获取
在这里插入图片描述
②选择应用顶部的发行 - 云打包 - 填写对应信息(证书等)
在这里插入图片描述

11.2 小程序打包

以微信小程序为例

①下载微信开发者工具,并开放端口供uniapp调用(设置-安全-打开服务端口)
②从uniapp直接跳转到微信开发者工具
在这里插入图片描述
③接下来的发布就和小程序发布一样了
详情参考:https://blog.csdn.net/weixin_45565886/article/details/130918238

填写AppId等

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/720483.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Android 实现透明度

开发时&#xff0c;UI上的一些布局总需要设置他是有一定的透明度的&#xff0c;有些UI不会给AHEX的代码&#xff0c;只有无透明度的HEX颜色代码&#xff0c;我也懒得去算&#xff0c;每次都要去网上查&#xff0c;所有今天自己总结一份&#xff0c;下次懒得再去找了。 1.颜色C…

群测群防体系建设自然灾害风险识别预警监测建设方案

实现感知全域覆盖实现监测全面汇聚实现风险早期识别实现预报预警精细精准实现预警靶向发布实现全过程监测预警 健全完善水旱、地质、森林草原、气象、地震、农业等灾害监测感知手段&#xff0c;形成空、天、地一体化全覆盖的自然灾害监测感知网络体系。 基于空、天、地全覆盖…

Segment Anything:突破边界的图像分割新技术解析

Segment Anything论文地址&#xff1a;https://arxiv.org/pdf/2304.02643.pdf Segment Anything&#xff1a;突破边界的图像分割新技术解析 论文背景Segment Anything任务方法Segment Anything 模型架构图像编码器&#xff08;Image Encoder&#xff09;提示编码器&#xff08;…

黑马微服务课程cloud-demo项目出现No instances available for userservice错误解决办法

错误描述 如果你的cloud-demo项目当输入http://localhost:8080/order/101&#xff0c;想查看订单编号为101的数据&#xff0c;网页前端显示如下错误 IDEA显示错误&#xff1a; 07-05 16:39:16:251 ERROR 10056 — [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] …

ElasticSearch - 批量更新bulk死锁问题排查 | 京东云技术团队

一、问题系统介绍 监听商品变更MQ消息&#xff0c;查询商品最新的信息&#xff0c;调用BulkProcessor批量更新ES集群中的商品字段信息; 由于商品数据非常多&#xff0c;所以将商品数据存储到ES集群上&#xff0c;整个ES集群共划分了256个分片&#xff0c;并根据商品的三级类目…

Elasticsearch脚本查询

Elasticsearch脚本查询 什么/为什么 Scripting是Elasticsearch支持的一种专门用于复杂场景下支持自定义编程的强大的脚本功能&#xff0c;ES支持多种脚本语言&#xff0c;如painless&#xff0c;其语法类似于Java,也有注释、关键字、类型、变量、函数等&#xff0c;其就要相对…

AI绘画:Stable Diffusion 终极炼丹宝典:从入门到精通

本文收集于教程合集&#xff1a;AIGC从入门到精通教程汇总 我是小梦&#xff0c;以浅显易懂的方式&#xff0c;与大家分享那些实实在在可行之宝藏。 历经耗时数十个小时&#xff0c;总算将这份Stable Diffusion的使用教程整理妥当。 从最初的安装与配置&#xff0c;细至界面…

fdisk和df -h的区别以及如何看懂和提取信息

前几天要查看linux系统磁盘大小&#xff0c;但是发现fdisk和df -h出来的大小和信息不一样&#xff0c;了解了一下linux的磁盘分区和内存大小&#xff0c;查阅了相关资料&#xff0c;总结以下信息&#xff1a; 一、相关理念 在计算机中&#xff0c;存放信息的主要存储设备就是…

天猫数据分析工具(天猫实时数据)

后疫情时代&#xff0c;聚会、聚餐与送礼热度上涨&#xff0c;酒类产品既作为送礼首选又作为佐餐饮品的热门选手也受此影响迎来消费小高峰。在此背景下&#xff0c;白酒市场也开始复苏并不断加快速度。 根据鲸参谋电商数据分析平台的相关数据显示&#xff0c;2023年1月份至4月…

小程序 事件委托给父元素scrollview 获取不到子元素view的绑定的dataset值

点击事件委托到父元素&#xff1a;scrollview 减少多次循环绑定 &#xff1a; 通过点击事件的dataset判断了点击哪个子元素。 常能见到e.target或者e.currentTarget。 简单来说&#xff0c;currentTarget就是当前对象&#xff0c;target就是整个对象&#xff08;包含子元素&…

如何实现移动端侧边目录栏收缩,并监听点击目录栏以外则自动收缩

父组件&#xff0c;index界面&#xff0c;注意此时expend按钮在父组件中 <template><el-container><el-aside class"Aside"><MAside expendClick"expendClick" :message"message" /></el-aside><div class&qu…

2、CCesium二次开发环境搭建

CCesium是使用c和opengl实现的桌面三维地球&#xff0c;所以进行二次开发需要搭建c的开发环境。 在windows系统上c开发可以使用vs或cmake和mingw clion开发。本人使用mingwclion&#xff0c;如果使用其他ide那我也帮不了你。cmake是构建项目的&#xff0c;clion使用2020.1版本…

Lesson3-1:OpenCV图像处理---几何变换

几何变换 学习目标 掌握图像的缩放&#xff0c;平移&#xff0c;旋转等了解数字图像的仿射变换和透射变换 1 图像缩放 缩放是对图像的大小进行调整&#xff0c;即使图像放大或缩小。 API cv2.resize(src,dsize,fx0,fy0,interpolationcv2.INTER_LINEAR)参数&#xff1a; s…

数据结构 | 二叉排序树

一、数据结构定义 /* 二叉排序树 */ typedef int TreeType; typedef struct BSTNode {TreeType data;struct BSTNode* lchild, * rchild; }*BSTree, BSTNode;二、方法概览 BSTNode* CreateTreeNode(TreeType data); // 创建二叉树结点 BSTNode* InsertTree(TreeType data, BS…

Vulnhub靶机PWNLAB:INIT writeup

靶机介绍 靶机下载&#xff1a;https://www.vulnhub.com/entry/matrix-2,279/ ​ 个人微信公众号&#xff1a;网络安全学习爱好者 信息搜集 arp扫描存活主机 ​​​ 根据MAC地址比较靶机IP为​192.168.30.131 ​​ nmap扫描全端口及端口服、版本 ​​​ 目录扫描123…

通信相关知识(三) 接入网

接入网的定界 接入网的功能 用户口功能、业务口功能、核心功能、传送功能、接入网系统管理功能。 ADSL 非对称数字用户线路&#xff08;ADSL&#xff0c;Asymmetric Digital Subscriber Line&#xff09;是数字用户线路&#xff08;xDSL&#xff0c;Digital Subscriber Lin…

【Java从入门到大牛】Java基础语法

&#x1f525; 本文由 程序喵正在路上 原创&#xff0c;CSDN首发&#xff01; &#x1f496; 系列专栏&#xff1a;Java从入门到大牛 &#x1f320; 首发时间&#xff1a;2023年7月5日 &#x1f98b; 欢迎关注&#x1f5b1;点赞&#x1f44d;收藏&#x1f31f;留言&#x1f43e…

黑客(自学笔记)

黑客&#xff0c;对很多人来说充满诱惑力。很多人可以发现这门领域如同任何一门领域&#xff0c;越深入越敬畏&#xff0c;知识如海洋&#xff0c;黑客也存在一些等级&#xff0c;参考知道创宇 CEO ic&#xff08;世界顶级黑客团队 0x557 成员&#xff09;的分享如下&#xff1…

第一章:项目架构演变

1、在设计系统时&#xff0c;应该多思考 墨菲定律 1. 任何事都没有表面上看起来那么简单。 2. 所有的事做起来都会比你预计的时间长。 3. 可能出错的事总会出错。 4. 如果你担心某种情况发生&#xff0c;那么它就更有可能发生。 2、在划分时&#xff0c;也要思考康威定律。…

centos7安装zookeeper的环境变量配置导致用户登录不了系统

废话不多说&#xff0c;我修改的/etc/profile,如果这个文件改错会造成所有用户都登录不了系统。 第一步&#xff1a;解决进不了系统 1.在登陆界面按&#xff1a;alt ctrlf2进入命令模式&#xff0c;输入密码登录后再输入&#xff1a; /usr/bin/sudo /usr/bin/vi /etc/profile …