这篇文章记录了我学习uni-app以及在项目中使用uni-app过程中所总结的笔记,以这篇文章记录下来,供你们和我自己对uni-app进行整体的复习和巩固,下面主要将uni-app和vue进行对比记忆,巩固uni-app用法,同时总结了多个uni-app的api使用场景
1、首先对比uni-app与vue,从以下几点介绍uni-app和vue的区别:
1、目录不同
2、对页面之间跳转的路由配置不同
3、页面使用的标签不同
4、生命周期函数不同
5、一部分api不同
6、接收路由传递参数方式不同
7、对组件挂载配置不同
8、css样式适配单位不一样
9、用户登录操作的步骤不一样
2、然后在项目开发中积累了多个uni-app的使用场景:
1、调用 uni.previewImage() 方法预览图片(点击图片进入图片预览)
2、uni.setStorageSync()方法将数据保存在本地(类似于vue的localStorage)
3、uni.showToast()显示提示信息弹框
4、调用 uni.setTabBarBadge() 方法,为底部导航栏的图标设置右上角的徽标
5、调用小程序提供的 chooseAddress() 方法,可使用选择收货地址的功能
6、uni.showModal()显示选择提示框,uni.openSetting() 进入授权页面让用户进行授权
7、通过uni.getUserProfile()获取登录用户信息以及uni.login()获取登录凭证code完成用户的登录操作
8、完整的微信支付功能开发流程(调用uni-app提供的uni.requestPayment()发起微信支付)
9、rpx
10、uni.chooseImage选择本地图片和uni.uploadFile上传服务器配合实现选择本地图片并上传服务器
11、uni-app提供的picker组件实现底部滑出的滑块选择列表
12、uni-app的App.vue的onLanuch生命周期和页面onLoad生命周期的执行顺序问题
13、uni-popup配合uni-popup-dialog实现弹窗确认框效果
3、最后整体记录了使用uni-app进行项目开发的基础知识
接下来我会按照上面的顺序详细的介绍uni-app的使用:
1、目录不同
uni-app目录依赖原生小程序风格,比如分包的概念
vue中对不同的页面只需要在views文件夹中定义不同组件,然后配置路由跳转就行了,所有页面都是这样,
而uni-app只有底部导航栏对应的几个页面才能定义在pages文件夹下,其余的页面都需要定义在subpkg文件夹下
2、对页面之间跳转的路由配置不同
uni-app在package.json文件中对底部导航栏页面和其他分包页面的路由进行配置
而vue统一在router文件夹下进行路由配置,且文件夹名没有限制
3、页面使用的标签不同
uni-app标签使用小程序使用的
等
uni-app中的部分标签是已经封装好了的功能,例如
轮播图标签,
滚动标签,只需要使用这些标签就可以实现对应功能
而vue中轮播图功能需要引入组件库使用组件库提供的标签或者自己通过很多代码来实现,滚动功能vue中需要使用better-scroll插件来实现,引入插件之后实现滚动功能包括监听滚动事件,实现上拉刷新等
4、生命周期函数不同
uni-app使用onLoad()等生命周期函数,且生命周期函数分为三类,而vue一套生命周期函数通用
5、一部分api不同
比如uni-app使用uni.$navigateTo()
等进行页面的跳转,而vue使用this.$router.push()
等进行跳转
6、接收路由传递参数方式不同
uni-app统一在onLoad(options)生命周期函数中携带的options参数获取路由传递的参数,
而vue通过this.$route.query获取路由参数
7、对组件挂载配置不同
vue生成的组件都要在使用的父组件身上引用定义成为局部组件,也可以在main.js中挂载成为全局组件
而uni-app只需要在components文件夹下新建组件文件,不需要进行任何挂载,直接使用就行了,组件使用的名字就是components文件夹里定义组件的文件名
8、css样式适配单位不一样
小程序使用rpx进行适配,vue使用rem/vm进行适配
9、用户登录操作的步骤不一样
vue:获取用户的用户名和密码等直接发送请求从后端获取数据和token信息完成登录
小程序:需要先进行微信通过uni.getUserProfile拉取用户信息,然后再调用uni.login()获取登录凭证code,最后才能通过前面两步获取到的参数向服务器发送请求获取token信息完成登录
1、调用 uni.previewImage() 方法预览图片(点击图片进入图片预览)
uni.previewImage({
// 预览时,默认显示图片的索引
current: i,
// 所有图片 url 地址的数组
urls: []
})
2、uni.setStorageSync()方法将数据保存在本地(类似于vue的localStorage)
//以字符串形式保存,所以经常使用JSON.stringify方法,保存的数据是数字/数组/对象就要使用JSON方法转为字符串保存,如果保存的数据本来就是字符串那么就不需要使用JSON方法
uni.setStorageSync('保存名', JSON.stringify('保存值'))
//getStorageSync获取保存到本地的数据
uni.getStorageSync(JSON.parse('保存的名称')) //JSON.parse解析字符串
3、uni.showToast()显示提示信息弹框
uni.showToast({
title, //显示内容
duration,
icon: 'none', //图标
})
4、调用 uni.setTabBarBadge() 方法,为底部导航栏的图标设置右上角的徽标
uni.setTabBarBadge({
index: 2, //索引用于确定为导航栏里哪一个图标设置徽标(0、1、2、3...)
text: '1', // 注意:text 的值必须是字符串,不能是数字
})
5、调用小程序提供的 chooseAddress() 方法,可使用选择收货地址的功能
//使用这个方法之后就可以在手机上正常选择收货地址了(包括对地址的添加、删除、修改以及地址定位的操作小程序都通过这个方法封装好了,我们直接调用这个方法就可以实现一个完整的地址选择的功能)
//注意uni.chooseAddress()是异步函数,需要使用async/await
async clickAddress(){
// 返回值是一个数组:第 1 项为错误对象;第 2 项为成功之后的收货地址对象
// 获取地址成功后第一项的err为null,第二项的succ为一个包含地址信息的对象
const [err, succ] = await uni.chooseAddress().catch(err => err)
// 用户成功的选择了收货地址
if (err === null && succ.errMsg === 'chooseAddress:ok') {
// 为 data 里面的收货地址对象赋值
this.address = succ
}
}
6、uni.showModal()显示选择提示框,uni.openSetting() 进入授权页面让用户进行授权
//uni.showModal()和uni.openSetting()配合让用户对小程序进行授权
// 调用此方法,重新发起收货地址的授权
async reAuth() {
// 3.1 提示用户对地址进行授权
const [err2, confirmResult] = await uni.showModal({
content: '检测到您没打开地址权限,是否去设置打开?',
confirmText: "确认",
cancelText: "取消",
})
// 3.2 如果弹框异常,则直接退出
if (err2) return
// 3.3 如果用户点击了 “取消” 按钮,则提示用户 “您取消了地址授权!”
if (confirmResult.cancel) return uni.$showMsg('您取消了地址授权!')
// 3.4 如果用户点击了 “确认” 按钮,则调用 uni.openSetting() 方法进入授权页面,让用户重新进行授权
if (confirmResult.confirm) return uni.openSetting({
// 3.4.1 授权结束,需要对授权的结果做进一步判断
success: (settingResult) => {
// 3.4.2 地址授权的值等于 true,提示用户 “授权成功”
if (settingResult.authSetting['scope.address']) return uni.$showMsg('授权成功!请选择地址')
// 3.4.3 地址授权的值等于 false,提示用户 “您取消了地址授权”
if (!settingResult.authSetting['scope.address']) return uni.$showMsg('您取消了地址授权!')
}
})
}
7、通过uni.getUserProfile()获取登录用户信息以及uni.login()获取登录凭证code完成用户的登录操作
<!-- 登录按钮 -->
<!-- 登录按钮必须指定 open-type="getUserInfo"才能获取用户信息 -->
<button type="primary" class="btn-login" open-type="getUserInfo" @click="getUserInfo">一键登录</button>
getUserInfo(){
//调用uni.getUserProfile()获取登录用户信息(微信弹窗授权)
uni.getUserProfile({
desc: '用于完善用户资料', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写
//成功后的回调函数,res保存了用户信息(用户点击确定授权)
success: (res) => {
//获取用户信息后调用uni.login()获取到了凭证code并整理参数发送请求获取token
this.getToken(res)
},
//失败后的回调(用户点击拒绝授权)
fail:(err)=>{
if(err.errMsg==="getUserProfile:fail auth deny"){
uni.$showMsg('您取消了授权')
}
}
})
},
// 调用登录接口,获取永久的 token
async getToken(info) {
// 调用微信登录接口获取登录凭证code
const [err, res] = await uni.login().catch(err => err)
// 判断是否 uni.login() 调用失败
if (err || res.errMsg !== 'login:ok') return uni.$showError('登录失败!')
// 准备发请求需要的参数对象
const query = {
code: res.code,
encryptedData: info.encryptedData,
iv: info.iv,
rawData: info.rawData,
signature: info.signature
}
// 发送请求获取 token(token为loginResult.message.token)
const {data:loginResult} = await uni.$http.post('/api/public/v1/users/wxlogin', query)
if (loginResult.meta.status !== 200) return uni.$showMsg('登录失败!')
uni.$showMsg('登录成功')
}
}
8、完整的微信支付功能开发流程(调用uni-app提供的uni.requestPayment()发起微信支付)
async pay(){
// 1. 创建订单
// 1.1 配置获取订单编号的请求参数
const orderInfo = {
}
// 1.2 发起请求创建订单
const { data:res } = await uni.$http.post('/api/public/v1/my/orders/create', orderInfo)
if (res.meta.status !== 200) return uni.$showMsg('创建订单失败!')
// 1.3 得到服务器响应的 “订单编号”
const orderNumber = res.message.order_number
// 2. 订单预支付
// 2.1 发起请求获取订单的支付信息
const { data: res2 } = await uni.$http.post('/api/public/v1/my/orders/req_unifiedorder', { order_number: orderNumber })
// 2.2 预付订单生成失败
if (res2.meta.status !== 200) return uni.$showError('预付订单生成失败!')
// 2.3 得到订单支付相关的必要参数
const payInfo = res2.message.pay
// 3. 发起微信支付
// 3.1 调用 uni.requestPayment() 发起微信支付
const [err, succ] = await uni.requestPayment(payInfo)
// 3.2 未完成支付
if (err) return uni.$showMsg('订单未支付!')
// 3.3 完成了支付,进一步查询支付的结果
const { data: res3 } = await uni.$http.post('/api/public/v1/my/orders/chkOrder', { order_number: orderNumber })
// 3.4 检测到订单未支付
if (res3.meta.status !== 200) return uni.$showMsg('订单未支付!')
// 3.5 检测到订单支付完成
uni.showToast({
title: '支付完成!',
icon: 'success'
})
},
9、rpx
1px = 2rpx是不准确的,rpx是响应式单位,以750px为基准宽度,根据设备屏幕宽度自动调整
10、uni.chooseImage选择本地图片和uni.uploadFile上传服务器配合实现选择本地图片并上传服务器
//修改头像
changeImage(){
//回调函数的箭头指向问题导致回调函数的this指向的不是vue组件,定义that将组件的this保存下来
const that = this
//从本地选择图片
uni.chooseImage({
count:1,
success(res) {
const images = res.tempFilePaths
//图片选择完成,发请求将图片上传到服务器
images.forEach(image=>{
uni.uploadFile({
url:"https://mfxy.tanghaolun.cn/api/v1/common/upload",
filePath:image,
name:"file",
formData:{
"type":1,
"img_type":'dynamic'
},
success(mes){
const data = JSON.parse(mes.data)
//图片上传出错
if(data.errNo!=0){
uni.showToast({
title:data.errstr,
icon:"error"
})
return
}
//图片上传成功返回图片,将头像信息展示保存在个人信息页面,如果点击保存,再保存到仓库
that.userInfo.image = data.data
}
})
})
}
})
},
注:回调函数的this指向函数本身,导致回调函数的this指向的不是vue组件,不能通过this.调用组件方法和数据解决办法:定义that将组件的this保存下来 const that = this
11、uni-app提供的picker组件实现底部滑出的滑块选择列表
12、uni-app的App.vue的onLanuch生命周期和页面onLoad生命周期的执行顺序问题
需求:在App.vue的onlanuch中执行登录请求获取token,在其他请求的请求头带上token,在页面的onload中发请求(携带token)获取数据,但是会发现获取不到数据,检查发现是onLoad中发的请求没有token
原因:App.vue的onLanuch生命周期和页面onLoad生命周期是同步执行的,甚至onLoad执行更快,所以onLoad中发请求时onLanuch中的登录并未完成,未获取到token,所以onLoad发的请求没有token,获取不到数据
解决办法:
1、main.js中添加代码:
Vue.prototype.$onLaunched = new Promise(resolve => {
Vue.prototype.$isResolve = resolve
})
2、在 App.vue 的 onLaunch 中增加代码this.$isResolve()
注意:这个方法必须在你的业务如登录逻辑执行完毕后再执行
3、在页面 onLoad 中增加代码 await this.$onLaunched注意onload要添加async,否则编译不过去
async onLoad(option) {
//等待登录成功(等待onLanuch执行结束)
await this.$onLaunched;
// 后续业务逻辑
},
13、uni-popup配合uni-popup-dialog实现弹窗确认框效果
1、hbuilderx上创建项目:
打开hbuilderx->点击左上角文件->新建->点击项目->选择uni-app项目和uni-ui模板->点击创建
2、hbuilderx连接微信开发者工具并编译运行项目:
(1)点击hbuilderx创建的项目中的manifest.json文件->点击微信小程序配置输入appid
(2)hubilderx中点击工具->设置->运行配置->下滑找到小程序运行配置->配置“微信开发者工具”的安装路径
(3)微信开发者工具中点击设置->安全设置->选择安全,开启服务端口
(4)在hbuilderx先点击选中当前要运行的项目,再点击hbuilderx中的运行 -> 运行到小程序模拟器 -> 微信开发者工具
(1)pages文件夹
下的每一个文件代表的是主路由页面,即tabbar导航栏对应的几个页面,每个文件在pages.json文件里的pages节点中都有对应的配置(path、style),代表的是主路由页面组件
鼠标右键点击pages文件夹,选择新建页面(选择scss模板),点击创建,会自动在pages文件夹下生成一个文件夹,文件夹下是与文件夹同名的.vue文件,在这个vue文件里面配置当前路由页面的代码和逻辑
(2)subpkg文件夹
下的每一个文件代表的是不是主路由页面的其他页面,比如说商品详情页,每个文件在pages.json文件里的subPackages节点中都有对应的配置(root、pages),相当于普通路由页面组件
创建页面的方式和在pages文件夹下创建页面一样
(3)components文件夹
下的每一个文件代表的就是一个组件,该文件下的.vue文件就是vue组件,鼠标右键点击 components文件夹选择新建组件就可以创建一个组件
需要注意的是在components文件夹里创建的组件不需要定义和引用,可以直接在页面中使用这些组件,组件名就是文件名,相当于自动将这些组件定义成了全局组件
(4)static文件夹
相当于vue的assets文件夹,在文件夹下新建images文件夹用于存放项目图片,新建css文件夹用于存放项目css样式文件
(5)store文件夹
是仓库文件夹,和vue中的vuex用法一样,文件夹下的index.js文件是主文件,store文件夹下新建modules文件夹用于存放子模块仓库js文件,然后通过export导出state等,在index.js中引入并挂载,最后在项目根目录下的main.js中引入store文件夹的index.js文件并挂载到vue实例中
uni-app中对vuex仓库的使用方法和vue中一样,包括子模块定义,state/mutations/actions/getters等的定义,以及在组件中使用vuex仓库都和vue方法一样,也可以使用辅助函数
注:state/mutations/actions/getters在uni-app的vue2用法中定义都是对象形式 const state = {}
(6)api文件夹
是自定义文件夹,一般用于封装请求函数,uni-app不能使用axios,官方提供的request请求函数又不支持请求拦截和响应拦截等,所以在uni-app中使用请求插件@escook/request-miniprogram
(需要npm下载)
api文件夹中对请求的二次封装格式可以和vue的请求二次封装一样
文件夹下新建request.js
用于对请求的baseurl、timeout、请求拦截和响应拦截等做一些封装然后导出配置好的请求函数
文件夹下新建index.js
文件,然后导入request.js文件中导出的请求函数,然后通过调用请求函数封装发请求的函数,比如登录、获取首页数据等
然后在需要发请求的组件中引入api/index.js中对应的请求函数,然后直接调用就行了,如果不想每次都调用,可以在main.js中引入api/index.js中的所有函数(import *),然后将这些函数组成的对象挂载到vue原型对象上(Vue.prototype.$request = 请求函数对象
),或者挂载到uni上(uni.$request = 请求函数对象)
(7)mixins文件夹
用于定义混入的一些方法,混入的定义方式、导出导入方式都和vue中的用法一样
(8)main.js
是项目的入口文件,app.vue
是页面的入口文件,都和vue一样
(9)pages.json
是uni-app项目的配置文件,很重要
1、路由:pages节点和subPackages节点
uni-app项目没有像vue一样的router文件夹来特地对路由进行配置,uni-app项目是通过pages文件夹+subpkgs文件夹(或者其他多个文件夹)配合pages.json文件中的pages节点和subPackages节点配置来对路由进行约定声明
在pages文件夹下定义的tabbar主页面然后在pages.json的pages节点中进行配置后就是主路由,在subpkgs文件夹在定义的普通页面然后在pages.json的subPackages节点中进行配置后就是普通的路由,都是通过path指定文件路径,path指定的文件路径也是路由进行跳转的url路径
每个页面的配置代码中的style属性可以设置当前页面的样式和功能(覆盖globalStyle节点节点中设置的全局样式)
style:{
"navigationBarBackgroundColor":"#000000" //当前页面导航栏背景颜色
"navigationBarTextStyle":"black" //当前页面导航栏标题颜色,仅支持black/white(默认white)
"navigationBarTitleText":"标题" //当前页面导航栏标题文字内容
"backgroundTextStyle":"dark" //当前页面下拉loading的样式,仅支持dark/light(默认dark)
"enablePullDownRefresh":false //是否为当前页面开启下拉刷新的效果(默认false)
"onReachBottomDistance":50 //页面上拉触底事件触发时距页面底部距离,单位为px(默认50)
"navigationStyle":"custom" //是否要自定义头部(定义为custom就自定义头部)
}
2、tabbar导航栏:tabBar节点
tabBar节点对tabbar导航栏进行配置,一般用于底部导航栏的配置,包括背景色、选中图片、未选中图片等
注意:tabbar导航栏配置后是小程序提供的默认样式的导航栏,如果需要使用自己的样式,可以自定义导航栏(具体配置网上查)
3、全局设置小程序窗口外观:globalStyle节点
uni-app中使用globalStyle节点编译到微信开发者工具中之后是window节点
globalStyle节点节点中的配置属性和页面中的style属性中的配置项一样
也可以在每个页面在pages.json中的配置中的style属性中单独设置样式来覆盖全局样式
1、应用生命周期函数(在app.vue中使用)
//小程序初始化完成时执行,全局只触发一次,可以做一些初始化的工作
onLaunch(){}
//小程序启动,或从后台进入前台显示时触发
onShow(){}
//小程序从前台进入后台时触发
onHide(){}
2、页面生命周期函数(在pages文件夹和subpkgs文件夹下的页面组件中使用)
//监听页面加载,一个页面只调用1次
onLoad(options) {
//路由传递的参数都统一在onLoad生命周期函数的options参数中接收
}
//监听页面显示
onShow(){}
//监听页面初次渲染完成,一个页面只调用1次
onReady(){}
//监听页面隐藏
onHide(){}
//监听页面卸载,一个页面只调用1次
onUnload(){}
3、组件生命周期函数(在components文件夹下的组件中使用)
// 组件自身的生命周期函数
//在组件实例刚刚被创建时执行(主)
created(){}
//在组件实例进入页面节点树时执行(主)
attached(){}
//在组件在视图层布局完成后执行
ready(){}
//在组件实例被移动到节点树另一个位置时执行
moved(){}
//在组件实例被从页面节点树移除时执行(主)
detached(){}
//每当组件方法抛出错误时执行
error(object Error){}
// 组件所在页面改变时触发的组件的生命周期函数
//组件所在的页面被展示时执行
show(){}
//组件所在的页面被隐藏时执行
hide(){}
//组件所在的页面尺寸变化时执行
resize(object Size){}
导航传参
//导航传参都是以query的形式跟在路径后面传递,然后在跳转到的页面组件中的onLoad生命周期的参数中接收
//比如
uni.navigateTo({
url: '/subpkgs/detail/detail?id=1&name=uniapp'
});
声明式导航: 使用
组件跳转
(1)跳转到tabbar导航页面(pages文件夹下定义的页面)url表示要跳转的页面的地址,必须以’/'开头open-type表示跳转的方式,必须为switchTab
示例代码如下:
<navigator url="/pages/message/message" open-type="switchTab">跳转到消息页面</navigator>
(2)跳转到普通页面(subpkgs文件夹下定义的页面)
url表示要跳转的页面的地址,必须以’/'开头open-type表示跳转的方式,必须为navigate,可以省略
示例代码如下:
<navigator url="/subpkgs/detail/detail">跳转到详情页</navigator>
编程式导航:
(1)跳转到tabbar导航页面(pages文件夹下定义的页面)
uni.switchTab({
url: '/pages/index/index',
//跳转成功的回调函数
success:()=>{}
//跳转失败的回调函数
fail:()=>{}
//跳转结束的回调函数(跳转成功、失败都会执行)
complete:()=>{}
});
(2)跳转到普通页面(subpkgs文件夹下定义的页面)
//跳转并传参
uni.navigateTo({
url: '/subpkgs/detail/detail?id=1&name=uniapp'
});
(3)后退导航
uni.navigateBack()
不再使用vue的localStorage
以下都是同步持久化存储数据,也可以去官网看异步持久化存储数据的方法
//保存到小程序Storage
uni.setStorageSync('storage_key', 'hello');
//获取key对应的Storage
const value = uni.getStorageSync('storage_key');
//获取当前的Storage信息
const res = uni.getStorageInfoSync();
//删除key对应的Storage
uni.removeStorageSync('storage_key');
//清空Storage
uni.clearStorageSync();
1、
替换vue的
2、
替换vue的
text标签加上selectable属性可以实现长按选中文本内容
3、
相当于v-html的功能
4、
标签实现滚动功能,相当于移动端better-scroll插件的滚动功能
scroll-view标签设置scroll-x
和scroll-y
配合css实现横向滚动和纵向滚动
5、
配合
实现轮播图效果
<swiper v-for="i in 4" indicator-dots>
<swiper-item>
<image src="" />
</swiper-item>
</swiper>
swiper标签的属性:
indicator-dots 是否显示面板指示点 indicator-color 指示点颜色 indicator-active-color 当前选中的指示点颜色 autoplay 是否自动切换 interval 自动切换时间间隔 circular 是否采用衔接滑动
6、标签实现按钮样式
<button size="mini" plain>默认按钮button>
<button type="primary" size="mini" plain>主色调按钮button>
<button type="warn" size="mini" plain>警告按钮button>
button标签的属性:
type 指定按钮类型
size 指定按钮大小
plain 指定按钮是否镂空
7、
标签显示图片及控制图片的大小及适配
<image src="/images/1.png" mode="widthFix">image>
image标签的mode属性指定图片缩放模式:
scaleToFill (默认值)缩放模式,不保持纵横比缩放图片,使图片的宽高完全拉伸至填满image元素
aspectFit 缩放模式,保持纵横比缩放图片,使图片的长边能完全显示出来。也就是说,可以完整地将图片显示出来。
aspectFill 缩放模式,保持纵横比缩放图片,只保证图片的短边能完全显示出来。也就是说,图片通常只在水平或垂直方向是完整的,另一个方向将会发生截取。
widthFix 缩放模式,宽度不变,高度自动变化,保持原图宽高比不变
heightFix 缩放模式,高度不变,宽度自动变化,保持原图宽高比不变
1、页面提供的方法
下拉刷新:
onPullDownRefresh(){
//下拉刷新不会主动停止,需要调用uni.stopPullDownRefresh()来停止
uni.stopPullDownRefresh()
}
上拉触底:
onReachBottom(){}
注意:上拉刷新和下拉触底涉及用户参与,为了避免用户频繁刷新发请求,应该对下拉刷新和上拉触底事件使用节流
2、小程序scroll-view组件提供的下拉刷新和上拉触底的功能
针对页面的下拉刷新和上拉触底只能以页面为单位,即不能自定义位置的问题,可以实现对scroll-view组件包裹的部分的上拉触底和下拉刷新
注意:页面提供的方法比scroll-view提供的下拉刷新和上拉加载的性能要好,能使用页面提供的就尽量使用
小程序不同于pc端/移动端网站,小程序的登录不需要用户输入用户名和密码,只需要授权获取用户信息
小程序需要先进行微信通过uni.getUserProfile()拉取用户信息,然后再调用uni.login()获取登录凭证code,最后才能通过前面两步获取到的参数向服务器发送请求获取token信息完成登录
uni-app和vue的区别主要在于目录结构、配置项、生命周期、api、标签
在vue组件中只有标签、生命周期函数以及一些小程序提供的api和事件不一样,其他的都和vue开发一样
比如:vue组件结构、父子组件通信、data/methods/computed/watch、mixins混入、v-for、@、:等这些指令、组件中vuex的使用等都是一样的