⼩程序Page,Component⼆次封装(符合vue2的开发习惯)
⼩程序 Page,Component ⼆次封装
前⾔
相信很多开发过⼩程序的开发者都应该知道,⼩程序在语法上⾯跟vue很像,但是⼜有点区别。本⽂将讲述如何对⼩程序
的Page页⾯构造器和Component构造器进⾏⼆次封装,抹平⼀些⼩程序与vue之间差别
⽬的
很多⼈可能会有疑问,为什么需要对Page和Component构造器进⾏⼆次封装。原因如下:
对于不是很熟悉⼩程序开发,但是熟悉vue开发的开发者来说,将Page和Component封装成更加符合vue开发习惯,能够让他们更加快速上⼿⼩程序。对于新⼿来说是很友好的。
可⾃定义钩⼦函数(⽣命周期函数)。在实际的项⽬开发者,很多⼩程序都是需要获取⽤户信息的,⽽且获取⽤户信息是
在app.js中的,但是页⾯的渲染跟app.js的执⾏是异步的,也就是说,页⾯的onLoad⽣命周期函数执⾏完毕了,app.js可能还没获取到⽤户信息,导致页⾯获取不到⽤户信息。这也是很多⼈遇见的问题,⽹上也有很多解决的⽅案,但是⽐较⿇烦。我们可以给⼆次封装的Page构造器⾃定义⼀个onAppLoad⽣命周期函数,该函数执⾏时间是在app.js获取完⽤户信息之后执⾏,这样⼦页⾯就可以获取得到⽤户的信息了。
扩展⾃定义功能。我们知道vue是可以使⽤watch监听属性和computed计算属性。⼩程序也可以⽀持的,但是需要第三⽅npm 包,使⽤起来⽐较⿇烦,我们也可以在⼆次封装中,把watch监听属性和computed计算属性添加进去,简化⼀些流程(引包,设置behaviors等)
统⼀管理。对于项⽬上来说,有些页⾯可能⽤户需要某种权限才能进来页⾯。基于这个需求,我们可以在⼆次封装好的Page构造器中,统⼀检查⽤户权限,⽽不是在每个页⾯中写⼀次检查权限。
Page 封装
Page 常⽤字段
我们先来看看 Page常⽤的字段有哪些,不常⽤的我就不列举出来了,可⾃⾏查看⽂档。
Page({
// 混⼊
behaviors:[],
// 页⾯数据
data:{},
// 页⾯加载完毕
onLoad(){},
// 页⾯显⽰出来
onShow(){},
// 页⾯渲染完毕
onReady(){},
// 页⾯卸载
onUnload(){},
// 上拉触底
onReachBottom(){},
// ⾃定义函数
onClick(){},
});
vue 常⽤字段
我们再看看vue有哪些常⽤的字段
export default{
mixins:[],
data(){
return{};
},
created(){},
mounted(){},
methods(){},
computed:{},
watch:{},
destroyed(){},
};
字段对应关系
从上⾯对⽐,我们不难发现⼩程序和vue字段的对应关系
Page.data -> vue.data
Page.behaviors -> vue.mixins
computed和watch⼩程序需要结合miniprogram-computed才能使⽤,我们在接下来会封装进去
onShow,onReachBottom等字段是Page构造器特有的,需要在封装的时候保留下来
在vue中,页⾯上的查询参数是存放在this.$route.query中的,但是⼩程序是在onLoad的回调参数中获取的,我们把⼩程序的页⾯查询参数挂载到this.$query中。
封装效果
最终我们封装出来的形式如下:
MyPage({
mixins:[],
data(){
return{};
},
//  也可以是
//  data:{},
created(){},
mounted(){},
methods(){
onClick(){}
},
computed:{},
watch:{},
destroyed(){},
onShow(){},
onReachBottom(){}
});
流程
实际上,很多字段都还是做了个映射⽽已,实际上并没有很⼤的改动。流程如下:
检查data字段是函数还是对象,如果是函数,就需要执⾏这个函数,获取返回的对象
将mixins,data,created,mounted,computed,watch,destroyed,onShow,onReachBottom等字段映射到⼩程序对应的字段上⾯
methods需要扁平特殊处理,因为⼩程序的⾃定义函数⽅法是跟data,onShow等字段同级的,是兄弟关系
检查是否使⽤了computed或者watch等字段,如果使⽤了,就⾃动给behaviors字段添加⼀个computedBehavior(通过miniprogram-computed引进来的)
重写onLoad⽣命周期函数,将页⾯地址的查询参数挂载到this.$query上
源码
最终代码如下:
import{ isFunction }from"./is";
import{ behavior as computedBehavior }from"miniprogram-computed";
function mapKeys(fromTarget, toTarget, map){
Object.keys(map).forEach((key)=>{
if(fromTarget[key]){
toTarget[map[key]]= fromTarget[key];
}
});
}
function proxyMethods(fromTarget, toTarget){
if(fromTarget){
Object.keys(fromTarget).forEach((key)=>{
toTarget[key]= fromTarget[key];
});
}
}
function proxyOnLoad(MyOptions, options){
// 保存原有的onLoad函数
const oldLoad = Load;
// 挂载查询参数
this.$query = query;
if(isFunction(oldLoad)){
// 执⾏原有的onLoad函数
oldLoad.call(this, query);
}
};
}
function proxyComputedAndWatch(MyOptions, options){
if(MyOptionsputed || MyOptions.watch){
options.behaviors = options.behaviors ||[];
// 如果使⽤到了`computed`或者`watch`,就需要添加对应的`behaviors`,否则⽆效
options.behaviors.push(computedBehavior);
}
}
function MyPage(MyOptions){
const options ={};
// 检查`data`字段是否为函数
if(isFunction(MyOptions.data)){
MyOptions.data = MyOptions.data();
}
}
// 字段映射
mapKeys(MyOptions, options,{
data:"data",
onReachBottom:"onReachBottom",
onShow:"onShow",
mounted:"onReady",
created:"onLoad",
mixins:"behaviors",
computed:"computed",
watch:"watch",
destroyed:"onUnload",
});
// 扁平methods字段中的数据
hods, options);
// 检查是否使⽤了`computed`或者`watch`字段
proxyComputedAndWatch(MyOptions, options);
// 重写`onLoad`⽣命周期函数,将页⾯地址的查询参数挂载到`this.$query`上
proxyOnLoad(MyOptions, options);
Page(options);
}
export default MyPage;
扩展⾃定义功能或者⽣命周期函数
我们以扩展⼀个onAppLoad⽣命周期函数为例,这个⽣命周期函数是在app.js的onLaunch函数执⾏完毕之后被调⽤改造 app.js
这个⽣命周期函数需要对app.js进⾏改造才能⽣效,改造点如下:
添加⼀个isLoad属性,⽤来标识app.js的onLaunch的函数是否执⾏完毕
添加⼀个taskList异步任务队列,存放需要在onLaunch函数执⾏完毕之后所以需要执⾏的任务
onLaunch函数中如果有异步任务,需要使⽤async和await等待异步任务执⾏完毕。
使⽤try-catch包裹函数体,在finally中,将isLoad属性标记为true,然后执⾏taskList中的任务try catch的使用方法
最终改造代码如下:
// app.js
App({
// 异步任务队列
taskList:[],
// 加载完毕
isLoad:false,
async onLaunch(){
// 加个try-catch,防⽌请求爆炸,taskList⽆法执⾏
try{
UserInfo();
// ...
}catch(error){
console.log("⾸页出现的错误", error);
}finally{
this.isLoad =true;
// 加载完毕就执⾏任务队列
this.runTask();
}
},
// 获取⽤户信息
async getUserInfo(params){
// ...
},
runTask(){
const taskList =this.taskList.slice();
if(taskList.length >0){
taskList.forEach((task)=>{
task();
});
this.taskList =[];
}
},
});
实现 onAppLoad 函数
app.js改造完成之后,我们需要准备⼀个函数,这个函数的作⽤就是通过getApp()获取⼩程序全局唯⼀的app实例(实际上就是app.js中的this),然后通过app.isLoad判断app.js中的onLaunch函数是否执⾏完毕了,最终返回⼀个Promise
代码如下:
// on-app-load.js
const app =getApp();
function onAppLoad(){
return new Promise((resolve, reject)=>{
try{
if(!app.isLoad){
app.taskList.push(()=>{
resolve();
});
}else{
resolve();
}
}catch(error){
reject(error);
}
});
}
export default onAppLoad;
重新改造 onLoad ⽣命周期函数

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。