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
- 在script标签中导入
- 在component中导入
- 在页面中引用
修改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_bannerthis.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 rpxwidth: 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_bannerthis.index_banner = res.data.index_bannerthis.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和coursecourseItemHandle(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.introducethis.introduceList = res.data.data.introduceListthis.Clist = res.data.data.Clistthis.imageT = res.data.data.imagethis.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等