uniapp跨平台项目开发实战

计划对标实战项目【蛋糕订购】

第一章、uniapp开发及调测相关介绍

第1节、移动端开发历史演进

HbuilderX

下载地址](https://www.dcloud.io/hbuilderx.html))

移动端开发技术演进

  1. 原生开发
    • Android Java、Kotlin 语言
    • iOS ObjectC、Swift 语言
    • 性能体验更好
    • 开发成本比较高
  2. Hybrid 混合开发
    • 核心功能
    • 非核心功能
    • 例如:京东
      • 核心功能:首页、分类、个人中心 采用原生
      • 非核心功能:积分商城、宣传页 采用H5前端 web-view
    • 原生页面与web页面之间的交互
      JSBridge
  3. 跨平台开发

    一套代码、多端运行

  • 打包iOS
  • 打包Andriod
  • 打包H5
  • 打包小程序
    • 微信小程序
    • 支付宝小程序
    • 百度小程序
  • 优点:极大降低开发成本
  • 缺点:性能体验比原生开发稍差,但是,目前的硬件状态下,体验几乎一样了

跨端技术方案汇总

  1. vue 技术栈
    • uniapp DCloud 跨14端,iOS、Android、web、小程序
      文档
  2. React技术栈
    • Taro 京东团队 iOS、Android、web、小程序
      文档
    • ReactNative FaceBook iOS、Android
      文档
  3. Flutter 谷歌团队 iOS、Android、web
  4. Electron 使用前端技术开发桌面应用
    文档

uniapp介绍及跨端实现

  1. 内置组件的使用,跟小程序几乎一样
    • view
    • image
    • text
    • button
  2. 动态交互语法,全面采用vue语法
    • v-for
    • v-if
    • v-model
    • ….

uniapp项目创建

  1. 参考群图片创建uniapp项目
  2. .vue文件扮演的角色
    • 扮演的页面,内部需要使用onLoad、onShow系列的生命周期
    • 扮演的公共组件,内部需要使用created系列生命周期
  3. 注意平台差异性 【在开发过程当中就要试试注意兼容性问题】
  4. 通过条件编译做不同平台适配
    文档](https://uniapp.dcloud.io/platform))

    1. #ifndef H5
    2. 这里的代码,只会在H5平台生效
    3. #endif
  5. uniapp跨端适配可能会遇到的问题
    文档](https://uniapp.dcloud.io/matter))

uniapp目录结构

  • components 公共组件
  • pages 存放项目页面
  • static 静态资源
  • App.vue 根组件
  • main.js 项目入口文件
  • menifest.json 项目配置文件(App打包相关配置、路由模式配置…)
  • pages.json 应用配置(底部菜单、导航栏….)
  • uni.scss 全局样式文件

uniapp开发流程

  1. 按需进行全局配置
    例如:底部菜单
  2. 进行页面布局

    • upx 作用跟rpx一样

      需要保证设计图宽度为750px 1px=1upx

    • Flex布局

    • 组件库
  3. 使用vue语法,做交互
    • 数据对接
    • 功能交互

组件库

  1. colorUI 倾向于布局
    文档)
    • 下载核心代码
    • 将colorui文件夹引入项目中
    • 使用组件
  2. uview 倾向于交互

    • 文档](https://www.uviewui.com/))

      第2节、HbuilderX工具安装及使用

      第3节、uniapp开发基本流程体验

      第4节、安卓真机调试配置

  3. 发行安卓App

下载链接

  1. 真机测试
  • 在电脑、手机同时安装 360手机助手
  • 用数据线,保证电脑的手机助手,成功连接到了手机(手机需要开启开发者模式)
  • 在HbuilderX中—-运行——手机或模拟器

    第5节、iOS真机调试配置

    第6节、微信小程序真机调试配置

第二章、uniapp框架基础及配置

第1节、页面局部配置及项目主题配置

第2节、pages.json全局配置底部导航

第3节、全局样式介绍及引入使用

第4节、iconfont字体图表库集成

第三章、框架数据交互基础

第1节、MVVM模式与数据驱动

第2节、v-bind属性动态控制

第3节、v-if与v-show实现条件渲染

第4节、v-on:tap事件基础及事件兼容

第5节、列表渲染v-for的使用

第6节、v-bind:key实现for循环的组件唯一性

第7节、v-for的嵌套循环使用

第8节、菜单切换案例实践及拓展

第四章、框架数据交互方法进阶

第1节、computed计算属性及其应用场景

计算 对于数据的处理(过滤、字符串反转)
属性 能够让我们像data数据包一样,在页面结构中使用
例如: 学员列表,如何展示其中不及格的部分学员

  • data 静态的数据包
  • computed 可以根据指定条件,从data中筛选符合条件的学员供我们使用

使用computed的优势:

  • 降低代码冗余度
  • 提高浏览器渲染性能
  • 计算属性内部对于数据的处理操作更加灵活
  • 能够自动根据data的变化,重新运算得到新的值
  1. 字符串翻转操作
  2. 按成绩筛选学员的功能

    第2节、computed实现数据过滤渲染

    实战: 实现按成绩筛选学员的功能

    第3节、watch监听及其应用场景

    负责监听数据(data、props)的变化,进而做出逻辑操作
    watch不会返回新数据

  3. 浅监听

  1. stu(){ //浅监听 stu
  2. //可以按需添加逻辑
  3. console.log('监听到了stu的变化');
  4. localStorage.setItem('stu',JSON.stringify(this.stu))
  5. },
  1. 深监听
  1. stu:{ //深监听
  2. handler:function(){ //监听到变化后的处理函数
  3. console.log('深度监听到了stu的变化');
  4. localStorage.setItem('stu',JSON.stringify(this.stu))
  5. },
  6. deep:true //开启深监听
  7. }

第4节、v-model实现数据双向绑定

  1. 单向绑定
  2. 双向绑定
  • input
  • textarea
  1. uniapp的某些表单元素无法支持双向绑定,需要通过@change事件,或者form表单来获取表单值
  • slider
  • checkbox

第5节、事件修饰符及其应用场景

  1. @事件(v-on)提供了事件修饰符:
  • .stop: 各平台均支持, 使用时会阻止事件冒泡,在非 H5 端同时也会阻止事件的默认行为
  • .native: 监听原生事件,各平台均支持
  • .prevent: 仅在 H5 平台支持
  • .capture: 仅在 H5 平台支持
  • .self: 仅在 H5 平台支持
  • .once: 仅在 H5 平台支持
  • .passive: 仅在 H5 平台支持
    1. <!-- 阻止单击事件继续传播 -->
    2. <view @click.stop="doThis"></view>
  1. 按键修饰符:uni-app 运行在手机端,没有键盘事件,所以不支持按键修饰符

    第6节、消息发送案例实践

第五章、项目启动及uniapp布局适配

第1节、项目启动及upx单位介绍

upx 相对单位,适配原则跟rpx相同

设计图宽度750px

第2节、项目公共样式分析及提取

第3节、商品列表页面布局实践

第六章、组件库及个人中心

第1节、ColorUI组件库介绍及使用

  1. 适用平台
  • 微信小程序
  • uniapp
  1. 文档

github仓库地址)
DCloud插件市场

  1. 熟悉ColorUI常用名称 ```typescript

.flex { display: flex; }

.basis-xs { flex-basis: 20%; }

.basis-sm { flex-basis: 40%; }

.basis-df { flex-basis: 50%; }

.basis-lg { flex-basis: 60%; }

.basis-xl { flex-basis: 80%; }

.flex-sub { flex: 1; }

.flex-twice { flex: 2; }

.flex-treble { flex: 3; }

.flex-direction { flex-direction: column; }

.flex-wrap { flex-wrap: wrap; }

.align-start { align-items: flex-start; }

.align-end { align-items: flex-end; }

.align-center { align-items: center; }

.align-stretch { align-items: stretch; }

.self-start { align-self: flex-start; }

.self-center { align-self: flex-center; }

.self-end { align-self: flex-end; }

.self-stretch { align-self: stretch; }

.align-stretch { align-items: stretch; }

.justify-start { justify-content: flex-start; }

.justify-end { justify-content: flex-end; }

.justify-center { justify-content: center; }

.justify-between { justify-content: space-between; }

.justify-around { justify-content: space-around; }

内外间距

.margin-0 { margin: 0; }

.margin-xs { margin: 10upx; }

.margin-sm { margin: 20upx; }

.margin { margin: 30upx; }

.margin-lg { margin: 40upx; }

.margin-xl { margin: 50upx; }

.margin-top-xs { margin-top: 10upx; }

.margin-top-sm { margin-top: 20upx; }

.margin-top { margin-top: 30upx; }

.margin-top-lg { margin-top: 40upx; }

.margin-top-xl { margin-top: 50upx; }

.margin-right-xs { margin-right: 10upx; }

.margin-right-sm { margin-right: 20upx; }

.margin-right { margin-right: 30upx; }

.margin-right-lg { margin-right: 40upx; }

.margin-right-xl { margin-right: 50upx; }

.margin-bottom-xs { margin-bottom: 10upx; }

.margin-bottom-sm { margin-bottom: 20upx; }

.margin-bottom { margin-bottom: 30upx; }

.margin-bottom-lg { margin-bottom: 40upx; }

.margin-bottom-xl { margin-bottom: 50upx; }

.margin-left-xs { margin-left: 10upx; }

.margin-left-sm { margin-left: 20upx; }

.margin-left { margin-left: 30upx; }

.margin-left-lg { margin-left: 40upx; }

.margin-left-xl { margin-left: 50upx; }

.margin-lr-xs { margin-left: 10upx; margin-right: 10upx; }

.margin-lr-sm { margin-left: 20upx; margin-right: 20upx; }

.margin-lr { margin-left: 30upx; margin-right: 30upx; }

.margin-lr-lg { margin-left: 40upx; margin-right: 40upx; }

.margin-lr-xl { margin-left: 50upx; margin-right: 50upx; }

.margin-tb-xs { margin-top: 10upx; margin-bottom: 10upx; }

.margin-tb-sm { margin-top: 20upx; margin-bottom: 20upx; }

.margin-tb { margin-top: 30upx; margin-bottom: 30upx; }

.margin-tb-lg { margin-top: 40upx; margin-bottom: 40upx; }

.margin-tb-xl { margin-top: 50upx; margin-bottom: 50upx; }

.padding-0 { padding: 0; }

.padding-xs { padding: 10upx; }

.padding-sm { padding: 20upx; }

.padding { padding: 30upx; }

.padding-lg { padding: 40upx; }

.padding-xl { padding: 50upx; }

.padding-top-xs { padding-top: 10upx; }

.padding-top-sm { padding-top: 20upx; }

.padding-top { padding-top: 30upx; }

.padding-top-lg { padding-top: 40upx; }

.padding-top-xl { padding-top: 50upx; }

.padding-right-xs { padding-right: 10upx; }

.padding-right-sm { padding-right: 20upx; }

.padding-right { padding-right: 30upx; }

.padding-right-lg { padding-right: 40upx; }

.padding-right-xl { padding-right: 50upx; }

.padding-bottom-xs { padding-bottom: 10upx; }

.padding-bottom-sm { padding-bottom: 20upx; }

.padding-bottom { padding-bottom: 30upx; }

.padding-bottom-lg { padding-bottom: 40upx; }

.padding-bottom-xl { padding-bottom: 50upx; }

.padding-left-xs { padding-left: 10upx; }

.padding-left-sm { padding-left: 20upx; }

.padding-left { padding-left: 30upx; }

.padding-left-lg { padding-left: 40upx; }

.padding-left-xl { padding-left: 50upx; }

.padding-lr-xs { padding-left: 10upx; padding-right: 10upx; }

.padding-lr-sm { padding-left: 20upx; padding-right: 20upx; }

.padding-lr { padding-left: 30upx; padding-right: 30upx; }

.padding-lr-lg { padding-left: 40upx; padding-right: 40upx; }

.padding-lr-xl { padding-left: 50upx; padding-right: 50upx; }

.padding-tb-xs { padding-top: 10upx; padding-bottom: 10upx; }

.padding-tb-sm { padding-top: 20upx; padding-bottom: 20upx; }

.padding-tb { padding-top: 30upx; padding-bottom: 30upx; }

.padding-tb-lg { padding-top: 40upx; padding-bottom: 40upx; }

.padding-tb-xl { padding-top: 50upx; padding-bottom: 50upx; }

/ — 浮动 — /

.cf::after, .cf::before { content: “ “; display: table; }

.cf::after { clear: both; }

.fl { float: left; }

.fr { float: right; }

  1. <a name="bV9if"></a>
  2. #### **第2节、使用ColorUI实现"零样式"页面布局**
  3. <a name="fAjTr"></a>
  4. #### **第3节、个人中心布局完善**
  5. <a name="Rbmmb"></a>
  6. #### **第4节、uView组件库集成**
  7. [文档]([https://www.uviewui.com/](https://www.uviewui.com/))
  8. > 如果uniapp自带组件能完成的交互,尽可能不选第三方组件库。
  9. > 功能性的组件,可以选择uView
  10. > 样式布局相关的,可以选择ColorUI
  11. 采用npm的方式安装,参考文档:[https://www.uviewui.com/components/npmSetting.html](https://www.uviewui.com/components/npmSetting.html)
  12. <a name="Q1Pbr"></a>
  13. #### ** **<br /><br />
  14. <a name="MhHot"></a>
  15. # **第七章、uniapp的路由方法及路由传参**
  16. <a name="RLbUI"></a>
  17. #### **第1节、uni.navigateTo及其路由传参**
  18. - 跳转并传递参数
  19. ```typescript
  20. handleDetail(idx){
  21. console.log(idx);
  22. uni.navigateTo({
  23. url:'../detail/detail?idx='+idx
  24. })
  25. }
  • 在onLoad生命周期中接收

    1. onLoad(options){
    2. console.log(options);
    3. }

    第2节、uni.navigateBack自定义返回

    第3节、uni.switchTab实现Tab页面访问

    第4节、其他路由方法的运用

    第八章、uniapp页面组件与公共组件

    第1节、页面组件与公共组件的异同

    页面组件,支持onLoad系列、created系列的生命周期,建议使用onLoad
    公共组件,只支持created系列

    第2节、页面组件的生命周期

    页面栈 uniapp为了提高项目性能,会维护一个页面栈,来缓存用户访问过的某一些页面

  • onLoad 一般用于初始化加载页面数据

  • onShow 解决页面数据实时更新的需求 个人中心—-登录——个人中心
  • onHide

    第3节、公共组件的全局注册与局部注册

    1. main.js中全局注册组件
    2. import MyComp from 'components/test-my-comp.vue'
    3. Vue.component('test-my-comp',MyComp)

    第4节、组件通信方案汇总

  1. 父子通信 props
  2. 子父通信 $emit
  3. 非父子关系组件通信 bus事件总线

第九章、项目首页开发

第1节、自定义页面导航栏

第2节、swiper轮播图应用及自定义配置

第3节、首页标题组件封装及复用

第4节、scroll-view区域滚动交互

  1. scroll-view组件使用及配置

    1. <scroll-view scroll-x >
    2. <view class="flex recommend">
    3. <image src="../../static/img/recommend1.jpg" mode="heightFix"></image>
    4. <image src="../../static/img/recommend2.jpg" mode="heightFix"></image>
    5. <image src="../../static/img/recommend3.jpg" mode="heightFix"></image>
    6. </view>
    7. </scroll-view>
  2. 如何让flex容器内的元素横向不要自动压缩

    1. .recommend{
    2. image{
    3. flex-shrink: 0;
    4. height: 290upx;
    5. }
    6. }

    第5节、商品组件封装及复用

    第6节、返回顶部功能实现

第十章、LeanCloud云服务

第1节、LeanCloud云服务介绍及应用容器创建

第2节、RestFull风格API介绍及使用

第3节、ApiFox测试接口可访问性

第4节、蛋糕商品分类数据录入

第十一章、异步请求及Promise封装

第1节、wx.request异步请求Rest接口数据

第2节、Promise对象及实践

一、自己封装uni.request

  1. 基于Promise对uni.request进行二次封装 ```javascript

import {ID,KEY,BASE_URL} from ‘../config’

function $http(url,method=”GET”,data={}){ return new Promise((resolve,reject)=>{ uni.request({ url:${BASE_URL}${url}, method, header:{ “X-LC-Id”: ID, “X-LC-Key”: KEY, “Content-Type”: “application/json” }, data, success: (res) => { resolve(res.data) }, fail: (err) => { reject(err) } }) }) }

function $get(url,data={}){ return $http(url,’GET’,data) }

function $post(url,data={}){ return $http(url,’POST’,data) }

export { $http, $get, $post }

  1. 2. main.js中对封装后的方法进行全局挂载
  2. ```javascript
  3. // 挂载异步请求方法
  4. // import {$http,$get,$post} from 'utils/request.js'
  5. // Vue.prototype.$http = $http
  6. // Vue.prototype.$get = $get
  7. // Vue.prototype.$post = $post
  8. import * as request from 'utils/request.js'
  9. for(let attr in request){
  10. Vue.prototype[attr] = request[attr]
  11. }

二、使用uview提供的异步方法

配置流程参考

第3节、使用Promise封装常用post、get方法

第4节、采用自定义异步方法请求并渲染Banner

第5节、使用web-view嵌入网页

第6节、编写自动化数据录入逻辑

第7节、自动转存商品数据逻辑

第十二章、商品列表渲染相关交互逻辑

第1节、商品列表渲染方法封装

第2节、LeanCloud约束查询及触底分页逻辑实现

第3节、数据请求的方法封装及下拉刷新交互

第4节、底部菜单结构自定义搭建

第5节、底部菜单触发不同分类数据渲染

第6节、分类遮罩交互渲染

第十三章、vuex状态管理器应用

第1节、vuex集成及基本使用流程

第2节、分析使用vuex存储商品数据切换条件

第3节、vuex的模块化拆分、state与mutations结合实践

第4节、分类菜单触发商品数据刷新

第5节、数据为空的交互处理

第十四章、注册登录功能

第1节、利用DCloud插件市场快速构建登录注册页

第2节、LeanCloud用户系统实现用户注册功能

第3节、用户登录功能及vuex状态机的完整数据流

第4节、用户信息持久存储及跨组件使用

第5节、用户头像上传及sessionToken的运用

第十五章、商品详情及购物车搭建

第1节、路由跳转及详情数据渲染

第2节、购物车页面搭建

第十六章、购物车页面交互

第1节、mapGetters结合mapMutations实现单选、全选功能

第2节、购物车编辑弹窗搭建及基本交互

第3节、购物车弹窗下拉规格选择交互

第4节、商品规格数据渲染及数据动态交互

第5节、弹窗规格数据与购物车列表数据同步交互

第6节、购物车总价计算及弹窗交互逻辑完善

第7节、购物车新增及响应式数据

第8节、新增商品功能完善

第十七章、支付流程及地址管理功能

第1节、结算及支付流程分析

  1. 支付流程前端需要做的步骤

    立即结算 下订单 uni.request请求携带用户勾选的商品信息 【前端完成】 下订单后,后端会向前端下发订单相关信息,同时会下发能够唤起支付的参数包 【后端提供】 立即支付 使用后端下发的唤起支付的数据包,唤醒支付宝、微信 【前端完成】

  1. 唤起支付的方式
  • 在手机App里面购物 uni.requestPayment
  • 手机网页、电脑网页 通过后端提供的支付连接、扫码支付
  1. 支付流程图

参考链接

  1. 扫码真机体验

image.png

第2节、支付流程真机演示

第3节、购物车访问路由拦截

第4节、结算页面结构搭建

第5节、地址列表页面结构搭建

第6节、地址列表动态渲染及设为默认功能交互

第7节、默认地址与配送地址的联动

第8节、配送地址交互优化

第十八章、收货地址录入及底部菜单封装

第1节、地图显示配置及地址详情页搭建

第2节、通过form表单录取地址数据

第3节、向LeanCloud存储收货地址信息

第4节、初始化加载用户地址列表

第5节、默认地址的在线数据状态修改

第6节、底部菜单独立封装

第十八章、项目打包及跨端部署

!!!注意!!! 为了节省项目开发时间,本项目并没有过多处理个别平台的兼容问题。 本节打包用的是前期代码比较少的版本来演示的,如果需要让整个项目最终在开发完毕后能够顺利发布到各个平台,我们需要在开发过程中,定期对各个平台的兼容性做调整,避免后期因无法准确定位兼容问题出现的位置,导致跨端发布失败。

第1节、Nginx服务器部署项目web端

第2节、微信小程序打包及预览

第3节、Android应用打包与内测平台分发