背景
从最早发布的微信小程序,到后来的支付宝小程序、钉钉小程序,字节跳动小程序、百度小程序、QQ小程序等,面对这么多套的代码,开发者去编写多套原生代码的成本显然非常高,使用H5的话体验又没有原生好,这时候只需编写一套代码,就能够适配多端的能力就显得尤为需要。
下面进入正题,给大家介绍下uni-app字节小程序的开发。
前置准备工作
默认头条小程序的APPID已申请成功
安装开发工具
百度小程序开发者工具
字节跳动开发者工具
HBuilderX或者其他自己喜欢的IDE都可以
项
目开发
可以通过HBuilderX可视化界面 以及 vue-cli命令行方式进行创建
下面主要介绍下通过vue-cli命令行这种方式来新建项目
全局安装vue-cli
npm install -g @vue/cli
创建
vue create -p dcloudio/uni-preset-vue user-uni-order
安装成功后提示选择模板,我们选择默认模板就可以了
项目整体流程
用户下单最短路径:首页下单-> 订单状态-> 完成支付, 如下: 综上我们需要做的页面维度:首页,地址检索,城市选择,登录,个人中心,订单列表,webview(收费标准 , 预估价格, 订单状态, 订单详情,法律条款)
制定目录结构
┌─components //uni-app组件目录
│ └─comp-a.vue //可复用的a组件
├─common // 通用的js&css工具等
├─hybrid //存放本地网页的目录
├─platforms //存放各平台专用页面的目录
├─pages //业务页面文件存放的目录
│ ├─index
│ │ └─components // 页级别组件
│ │ └─vuex // index页面vuex主要存放index的逻辑
│ │ └─index.vue // index页面
├─static //存放应用引用静态资源(如图片、视频等)
│ ├─mp-weixin //条件编译png
│ │ └─a.png
│ │ └─b.png
├─store // 状态统一管理,将各个页面的vuex汇总
├─service // 汇总请求,api等
│ └─api.js // 接口api相关
│ └─config.js // 环境配置
│ └─index.js
│ └─request.js // 网络请求
├─ttcomponents // 头条小程序自定义组件存放目录
├─main.js //Vue初始化入口文件
├─App.vue //应用配置,用来配置App全局样式以及监听
├─manifest.json //配置应用名称、appid、logo、版本等打包信息
└─pages.json //配置页面路由、导航条、选项卡等页面类信息
运行项目
想运行到哪个平台小程序,首先需要把相应的APPID, IDE路径对应填写正确
npm run dev:mp-toutiao // 实时监听编译
此时打开字节跳动IDE进行导入操作,就可以看见页面啦~~~
Tips:使用字节跳动编译器打开uni-app编译的小程序时,必须进行导入操作,而不是新建,因为新建会默认成代码片段,虽然也可以实时预览效果但是会导致上传功能确实
具体页面的开发
首页开发
项目中其他页面的目录结构与首页均相同,后面不做多余赘述。
├─pages
│ ├─index
│ │ └─components
│ │ └─vuex
│ │ │ └─index.js // 首页逻辑
│ │ └─index.vue
我们使用vuex来管理状态,每个页面都有自己的vuex, 其中index.js存放对应页面相关逻辑,为了避免频繁切换目录,把state, mutations, actions放在一个文件下,使用时并启用vuex的模块化,如下
const IndexPage = {
namespaced: true, // 启用模块化vuex
state: {
... // 需要共享的状态
},
mutations: {
... // 一些方法
},
actions: {
... // 请求相关
}
}
export default IndexPage //最后导出IndexPage
各个页面的vuex统一放在store里
import Vue from 'vue'
import Vuex from 'vuex'
import IndexPage from '../pages/index/vuex'
import AddressSearch from '../pages/address/vuex/index'
import CityListPage from '../pages/city-list/vuex/index'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
... // 全局共用的状态
},
mutations: {
},
actions: {
},
modules: {
IndexPage, // 首页vuex
AddressSearch, // 地址检索页vuex
CityListPage, // 城市列表页vuex
},
})
export default store
最后,在main.js里面引用
import Vue from 'vue'
import App from './App'
import store from './store'
Vue.config.productionTip = false
App.mpType = 'app'
const app = new Vue({
...App,
store
})
app.$mount()
完整的首页逻辑交互框架就搭建成功了,以下是开发首页时遇见的问题
首页开发遇到的问题
问题原因:引入的import swiper from "../../components/swiper/swiper"
,导致把自定义的swiper覆盖,所以不展示
解决:引入的import uniSwiper from "../../components/swiper/swiper"
,不和原组件命名冲突即可
问题原因:百度设置http请求header如果有中文字符
解决:使用条件编译,如果是百度小程序需要encodeURI 一下, 或者删除header的中文部分
uni-app的image标签,在小程序端不支持动态引入图片
// 引不到
// 可以引入
uni.getLocation() 只能获取经纬度,获取不到详细地址信息
非 h5 平台 :key 不支持表达式
由于:key="timer__${idx}
"的写法,编译时控制台会警告,但是不影响页面
{{item == "立即用车" ? "" : index == 1 ? "时" : index == 2 ? "分" : ""}}
父子组件传参,类型定义不对不提示错误信息,只展示null, 所以遇到null问题可以查看是否是类型定义不一致
uni-app中的watch不支持监听小程序,如下
watch: {
searchType (to) {
if (to) {
// 如果是起始地回填起始地信息否则回填目的地信息
if (to === SEARCH_TYPE.START) {
this.detailAddress = this.startAddress.detailAddress || ''
} else {
this.detailAddress = this.endAddress.detailAddress || ''
}
}
}
}
改成
mounted () {
if (this.searchType === SEARCH_TYPE.START) {
this.detailAddress = this.startAddress.detailAddress || ''
} else {
this.detailAddress = this.endAddress.detailAddress || ''
}
}
个人中心开发
// template
onLoad (options) {
console.log('H5入口页获取到的参数', options)
let { src, needLogin} = options
if(!needLogin){
this.src = decodeURIComponent(src)
return
}
// 需要登录的 就先获取临时token
this.fetchTempToken(src)
}
如果不需要登录的H5我们直接赋值到src即可,需要登录才能正常访问的页面,首先要获取临时token,拿到临时token后回传给服务端并且采用中间页redirectUrl的形式跳转。
个人中心开发遇到的问题
向网页传递信息要使用头条api的bindmessage
官方说明“网页向小程序 postMessage 时,会在特定时机(小程序后退、组件销毁、分享)触发并收到消息”
// 在小程序中调起H5中的打电话功能
onmessage (e) {
let { phoneNumber, name } = e.detail
if(name == 'makePhoneCall'){
uni.makePhoneCall({
number: phoneNumber
})
}
}
需要注意的web-view的bindmessage属性并不是实时的
真机拨打电话功能不能用
// 使用uni.makePhoneCall真机没反应
uni.makePhoneCall({ phoneNumber: '114'});
解决:改为头条api的tt开头
// 真机模拟器均可正常使用
tt.makePhoneCall({ phoneNumber: '114'});
登录开发
大致思路:
1.首先获取获取服务供应商的信息
2.调用uni.getProvider
获取授权code
3.获取用户的手机号(用户登录头条app的)
4.从@getphonenumber
回调中获取到用户信息
5.调用授权登录服务api
6.获取token, openid等信息
// template
授权登录更快捷
// 完成渲染调用授权code方法
mounted () {
this.getCode()
}
// 获取授权code方法
async getCode () {
const [ errorProvider, provider ] = await uni.getProvider({ service: 'oauth' })
if (errorProvider) {
console.log('获取provider失败')
return
}
const [ errLogin, data ] = await uni.login({
provider: provider.provider[0],
force: true
})
if (errLogin) {
console.log('获取code失败')
// 失败的操作,提示等
return
}
const { code } = data
this.code = code
},
// 头条获取到用户信息
async onGetPhoneNumber ({ detail }) {
const { errMsg } = detail
// 授权失败
if (errMsg.indexOf('auth deny') > -1) {
// 取消授权进行手机验证码登录
return
}
try {
// 调用服务授权接口
const { data } = await authLogin({
code: this.code,
...detail,
})
if (data.code === SUCCESS) {
// 存token, openid等操作
// 重新更新个人信息
} else {
// 失败的提示等
}
} catch (error) {
// 登录失败异常情况处理
}
},
// 百度获取到用户信息同理头条。。。
登录开发遇到的问题
手机验证码开发时,引入checkbox-group
报错,如下图:
原因:components : { [CheckBox.name]: CheckBox }
引入组件方式不支持
发布到测试环境
以字节跳动为例子,打开字节跳动开发者工具,在工具栏找到上传,填写版本号,发布。版本号不和上一次冲突就可以。
Tips: 前面有提过,新建代码片段是在开发者工具上是没有上传按钮的,要导入项目才可以。
上传成功后,会提示进入小程序开发者平台,现在可以看到开发者的版本。
上图二维码就可以只作为本次的体检版本来扫一扫了。
发布到正式环境
前置准备,在后台配置好相关线上域名
切换到线上环境
// 环境相关配置
export const ENV = {
// 开发环境
RD: 'rd',
// 测试环境
TEST: 'test',
// 沙箱环境
BOX: 'box',
// 线上环境
ONLINE: 'online'
}
// 环境切换
export function getCurrentEnv() {
return ENV.ONLINE // 正式环境切到online
}
在开发者工具中点击上传
去小程序开发者平台提审发布
发布成功后可在头条搜索栏中搜到,抖音的话目前只有安卓平台上线了小程序功能。
结束语
以上就是uni-app转字节跳动、百度小程序的部分开发,相信大家对uni-app实战小程序已经有了初步认识,也欢迎大家指正,互相交流,共同进步
在线体验
快去打开头条app搜索"快狗打车小程序"或者使用头条扫一扫体验一下吧~
推荐文章
如何更好解决跨域问题?uni-app改造记
uni-app脚手架踩坑记
好文我在看????