先提一个问题:如果你想在所有小程序方法执行之前额外执行一段逻辑,例如权限判断,你会怎么做?貌似在微信小程序中没有比较优雅的解决方法。
现在我向大家介绍下Behavior的definitionFilter选项
1、definitionFilter
定义:definitionFilter 是一个函数,在被调用时会注入两个参数,第一个参数(defFields)是使用该 behavior 的 component/behavior 的定义对象,第二个参数(definitionFilterArr)是该 behavior 所使用的 behavior 的 definitionFilter 函数列表。
1)defFields(参数一)
接下来我们来看下defFields到底是什么东西
首先看下Page的定义
再来看下defFields
- behaviors:当前页面使用的behaviors列表。
- data:当前页面中的data数据。
- methods:当前页面使用方法,包括生命周期方法。 总结一句话,函数会被放进methods中,其他的和定义段保持一致
那么defFields到底有什么用呢?
先贴一段官方的示例
// behavior.js
module.exports = Behavior({
definitionFilter(defFields) {
defFields.data.from = 'behavior'
},
})
// component.js
Component({
data: {
from: 'component'
},
behaviors: [require('behavior.js')],
ready() {
console.log(this.data.from) // 此处会发现输出 behavior 而不是 component
}
})
显然已经很明显了,它会在Page/Component生成之前修改(过滤)内部的各个选项。
2)definitionFilterArr(参数二)
definitionFilterArr是 behavior 所使用的 behavior 的 definitionFilter 函数列表。
以下举个例子来说明:
// behavior3.js
module.exports = Behavior({
definitionFilter(defFields, definitionFilterArr) {},
})
// behavior2.js
module.exports = Behavior({
behaviors: [require('behavior3.js')],
definitionFilter(defFields, definitionFilterArr) {
// definitionFilterArr[0](defFields)
},
})
// behavior1.js
module.exports = Behavior({
behaviors: [require('behavior2.js')],
definitionFilter(defFields, definitionFilterArr) {},
})
// component.js
Component({
behaviors: [require('behavior1.js')],
})
上述代码中声明了1个自定义组件和3个 behavior,每个 behavior 都使用了 definitionFilter 定义段。那么按照声明的顺序会有如下事情发生:
- 当进行 behavior2 的声明时就会调用 behavior3 的
definitionFilter函数,其中defFields参数是 behavior2 的定义段,definitionFilterArr参数即为空数组,因为 behavior3 没有使用其他的 behavior 。 - 当进行 behavior1 的声明时就会调用 behavior2 的
definitionFilter函数,其中defFields参数是 behavior1 的定义段,definitionFilterArr参数是一个长度为1的数组,definitionFilterArr[0]即为 behavior3 的definitionFilter函数,因为 behavior2 使用了 behavior3。用户在此处可以自行决定在进行 behavior1 的声明时要不要调用 behavior3 的definitionFilter函数,如果需要调用,在此处补充代码definitionFilterArr[0](defFields)即可,definitionFilterArr参数会由基础库补充传入。 - 同理,在进行 component 的声明时就会调用 behavior1 的
definitionFilter函数。
2、例子(简易权限判断)
//auth.js
Behavior({
...
definitionFilter(defFields) {
const methods = defFields.methods;
Object.keys(methods).forEach((name) => {
const f = defFields.methods[name];
//修改Page中的方法
defFields.methods[name] = function () {
if (/**权限判断 */) {
f.call(this);
}
}
})
},
...
});
这样做会修改Page中的方法,使它们在调用前进行一个逻辑判断。但是这同样会发生在生命周期方法上,并且可能某些方法我们并不需要添加这段逻辑,那该怎么办呢?
答案是你可以在Page中定义一个自定义段,不妨叫它authMethods。
Page({
behaviors: [auth],
//只能包含定义的方法名
authMethods:['fun1'],
fun1(){
console.log('fun1');
},
fun2(){
console.log('fun2');
},
})
修改Behavior
//auth.js
Behavior({
...
definitionFilter(defFields) {
const authMethods = defFields.authMethods;
authMethods?.forEach((name) => {
const f = defFields.methods[name];
//修改Page中的方法
if(f){
defFields.methods[name] = function () {
if (/**权限判断 */) {
f.call(this);
}
}
}
})
},
...
});
首先拿到自定义段authMethods,然后对它进行遍历,拿到方法名称,只对列表中定义的方法添加额外的逻辑。
当然,这只是一个非常简易的权限判断。
作者自己也定义了一个比较通用的权限判断behavios,欢迎使用。