vant 的使用我开始是 npm 导入,然后 import,使用不了。 找了各种方法,最后还是下载文件,然后找到 dist 文件夹,复制到项目里,我是放在 static 文件夹,文件名 dist 重命名为 vant。 在 app.json 里添加需要的组件,这是全局添加的,可以全局使用这些组件 "usingComponents": { "van-button": "../static/vant/button/index", "van-cell": "../static/vant/cell/index", "van-cell-group": "../static/vant/cell-group/index", "van-radio": "../static/vant/radio/index", "van-radio-group": "../static/vant/radio-group/index", "van-transition": "../static/vant/transition/index" }
flyio 的使用以前用的 axios,也没有仔细研究过,这次自己封装头痛不已。 我们使用 token 做登录信息(id 在 token 里面),做了一个单独的登录接口,获取 token,token 存在本地,并且 token 会过期。 接口自动判断是否需要 token ,如果需要就去拿,放在 header 里发过去,header 里添加新字段,如果有特殊字符比如下划线等,就需要 nginx 配置,比较不麻烦,驼峰命名比较方便。 如果本地没有 token 数据,就需要先暂停请求,重新获取 token,然后继续之前的请求。 如果响应返回 token 过期,就需要重新获取 token ,并且重新自动发起之前的请求。 请求与 token 之间的矛盾(fly 的暂停是使用拦截器的锁死,拦截器都停了,获取 token 的接口自然也就用不了了),我们需要在封装的时候把获取 token 的接口单独使用 fly 对象。 import Fly from 'flyio/dist/npm/wx' import { _GetToken } from "@/api/apiList"; const tokenFly = new Fly(); tokenFly.config.timeout = 10000; //设置超时 tokenFly.config.baseURL = process.env.API_ROOT; //填写域名 // 添加请求拦截器 tokenFly.interceptors.request.use(request => { request.headers = { "X-Tag": "flyio", 'Content-Type': "application/x-www-form-urlencoded", }; return request }, error => { Promise.reject(error) }) // 添加响应拦截器 tokenFly.interceptors.response.use(response => { // 统一处理一些响应的code状态 if (response.data.data.loginToken) { wx.setStorage({ key: "token", data: response.data.data.loginToken }) } return response.data }, err => { // 请求出错,根据返回状态码判断出错原因 if (err.status == 0) { wx.showToast({ title: `网络连接异常`, icon: 'none', duration: 5000 }) } else if (err.status == 1) { wx.showToast({ title: `网络连接超时`, icon: 'none', duration: 5000 }) } else if (err && err.response) { wx.showToast({ title: `连接错误,请稍后再试! ${err.response.status}`, icon: 'none', duration: 5000 }) } return Promise.resolve(err) }) const fly = new Fly() fly.config.timeout = 10000; //设置超时 fly.config.baseURL = process.env.API_ROOT; //填写域名 // 添加请求拦截器 fly.interceptors.request.use(request => { request.headers = { "X-Tag": "flyio", 'Content-Type': "application/x-www-form-urlencoded", }; let url = request.url; if (url.indexOf("login") > -1) { wx.removeStorageSync('token') request.headers.loginToken = ""; } if (url.indexOf("user") > -1 && url.indexOf("login") < 0) { if (!wx.getStorageSync('token')) { console.log('没有token,先请求token...'); fly.lock(); //锁定当前实例,后续请求会在拦截器外排队 return getToken().then(() => { wx.hideLoading() request.headers.loginToken = wx.getStorageSync('token'); return request }) .finally(() => { fly.unlock() // 解锁当前fly实例 }) } else { request.headers.loginToken = wx.getStorageSync('token'); } } return request }, error => { Promise.reject(error) }) // 添加响应拦截器 fly.interceptors.response.use(response => { // 统一处理一些响应的code状态 if (response.data.data.loginToken) { wx.setStorage({ key: "token", data: response.data.data.loginToken }) } if (response.data.code == -2) { wx.showLoading({ title: '本地登录已失效' }) console.log('本地已有token失效,即将请求新的token') fly.lock() // 锁定当前fly实例 return getToken().then(() => { wx.hideLoading() console.log('token已更新') }) .finally(() => { fly.unlock() // 解锁当前fly实例 }) .then(() => { console.log(`重新请求:path:${response.request.url},baseURL:${response.request.baseURL}`) return fly.request(response.request) }) } return response.data }, err => { // 请求出错,根据返回状态码判断出错原因 if (err.status == 0) { wx.showToast({ title: `网络连接异常`, icon: 'none', duration: 5000 }) } else if (err.status == 1) { wx.showToast({ title: `网络连接超时`, icon: 'none', duration: 5000 }) } else if (err && err.response) { wx.showToast({ title: `连接错误,请稍后再试! ${err.response.status}`, icon: 'none', duration: 5000 }) } return Promise.resolve(err) }) const getToken = () => { return new Promise((resolve) => { wx.getUserInfo({ success: function (infoRes) { console.log(infoRes); wx.login({ success(loginRes) { console.log(loginRes); if (loginRes.code) { wx.showLoading({ title: '正在重新登录' }) tokenFly.post('/pub/api/login', { code: loginRes.code, encryptedData: infoRes.encryptedData, iv: infoRes.iv, parentId: wx.getStorageSync("fromId") || "" }).then((flyReq) => { console.log(flyReq); console.log("token请求成功") wx.showLoading({ title: '重新登录已完成' }) resolve() }) } else { console.log("登录失败!" + loginRes.errMsg); } } }); }, fail: function (res) { console.log(res); wx.navigateTo({ url: "../auth/main" }); } }); }) } export default fly
mpvue 的使用
页面之间的传参// 页面跳转带参 wx.navigateTo({ url: `../exercise/main?levelId=${item.id}` }); // 页面路径参数获取 this.$root.$mp.query.levelId 图片的样式height 不会自适应,我添加了原生小程序的 mode 属性,实在不行就设置 height 吧。 按钮 bind 绑定的写法按钮的原生属性 bindxxxxxxxxx,bind 在 mpvue 中写成 @ 就好了, <button open-type="getUserInfo" @getuserinfo="getAuth" class="auth-btn">开始使用</button> 生命周期生命周期 destory 和 onUnlod,页面之间的切换,如果之前的页面有弹出框,切换到其他的页面然后再返回,这个弹出框还是显示的,之前的页面的数据是没被销毁的。 登录授权小程序改版之后,wx.getUserInfo 不会弹出授权框了,需要用户手动触发。我们做了一个授权页,在首页进入下一个页面的时候,判断本地是否有个人信息,如果没有就去拿用户信息,如果失败就去授权页。 // 判断去授权页 goMajorPath() { // console.log(item); let that = this; if (this.wxUserInfo && this.xfxUserInfo) { wx.navigateTo({ url: `../major/main` }); return; } // 拿用户信息,失败就去授权 wx.getUserInfo({ success: function(infoRes) { console.log(infoRes); that.CURMAJOR(item); that.WXUSERINFO(infoRes.userInfo); // 存储用户信息 wx.navigateTo({ url: `../major/main` }); }, fail: function(res) { console.log(res); wx.navigateTo({ url: "../auth/main" }); } }); }
// 授权逻辑 getAuth(e) { let that = this; if (e.mp.detail.userInfo) { console.log("授权通过"); wx.hideToast(); this.WXUSERINFO(e.mp.detail.userInfo); // 存储用户信息 this.action_XFXUSERINFO(); wx.navigateBack({ delta: 1 }); } else { console.log("拒绝授权"); wx.showToast({ title: "鉴于您拒绝授权,我们是无法保存您的答题数据的!", icon: "none", duration: 5000 }); } } 手机号获取获取手机号,也是单独做了一个页面,手动触发获取手机号 // 去手机号获取页 goLevelPath(item) { console.log(item); console.log(this.xfxUserInfo.phone); let that = this; if (this.xfxUserInfo.phone) { that.CURMAJOR(item); wx.navigateTo({ url: `../level/main?majorId=${item.id}` }); return; } //没有手机号跳转请求页面 wx.navigateTo({ url: "../phone/main" }); }
// 手机号获取 getPhone(e) { // console.log(e); // console.log(e.mp.detail); if (e.mp.detail.errMsg == "getPhoneNumber:ok") { this.action_savePhone(e.mp.detail); this.action_XFXUSERINFO(); wx.navigateBack({ delta: 1 }); } else { console.log("拒绝授权"); wx.showToast({ title: "鉴于您拒绝快捷登录,我们是无法保存您的答题数据的!", icon: "none", duration: 5000 }); } } 分享此功能实现传播,也算是核心业务了。分为顶部按钮分享和自定义按钮分享。需要在 mounted 生命周期设置分享功能,在 onShareAppMessage 生命周期写业务。自定义按钮需设置 open-type="share" mounted() { wx.showShareMenu({ withShareTicket: true }); }, onShareAppMessage: function(res) { console.log(res); //menu 没有 tartget if (res.from === "button") { return { title: `恭喜${this.xfxUserInfo.username},挑战[${ this.curMajor.name }]专业-${this.curLevel.levelName}${ this.coreNum >= 80 ? "成功!" : "完成,请再接再厉!" }`, path: `/pages/index/main?fromId=${this.xfxUserInfo.id}` }; } if (res.from === "menu") { return { title: "一起打卡学习,每天进步一点点", path: `/pages/index/main?fromId=${this.xfxUserInfo.id}` }; } } 分享的传播标记,分享的路径是可以带参的,这个参数就是分享传播者的标记,当新用户从这里进来,路径中是有这个标记的,我们直接在 App.vue 的 onLaunch 生命周期中,存储改标记到本地,当用户授权的时候和用户信息一起存起来。该生命周期还可以判断场景值,我是直接判断的参数。 onLaunch(opt) { console.log(opt); if (opt.query.fromId) { wx.setStorage({ key: "fromId", data: opt.query.fromId }); } }, 迭代更新onLaunch(opt) { //调用微信接口检查是否有新版本 const updateManager = wx.getUpdateManager(); updateManager.onCheckForUpdate(function (res) { // 请求完新版本信息的回调 console.log(res.hasUpdate); }); updateManager.onUpdateReady(function () { wx.showModal({ title: "更新提示", content: "新版本已经准备好,是否重启应用?", success: function (res) { if (res.confirm) { // 新的版本已经下载好,调用 applyUpdate 应用新版本并重启 updateManager.applyUpdate(); } } }); }); updateManager.onUpdateFailed(function () { // 新版本下载失败 wx.showModal({ title: "更新提示", content: "新版本下载失败", showCancel: false }); }); },
|
请发表评论