一、behavior的用处
在behavior的definitionFilter,可以进行一些初始化值的添加操作,并且能够添加methods,这也是进行绑定事件的重要部分
defFields.methods.bindDefFields = (function (defFields) {
let throttleObj= defFields.throttle || {}; //获取组件实例添加的throttle对象,为他定义的属性handler设置节流
let throttleKeyList = Object.keys(throttleObj);
for (let key of throttleKeyList) {
defFields.methods[key] = throttle(throttleObj[key].handler,throttleObj[key].delay);
}
}
将这个事件添加在defFields.methods对象上会在初始化时添加,就可以通过this.事件名调用behavior中定义的方法,通过与defFields.data的结合可以解决大部分问题
page.js
throttle:{
throttleScroll:{
handler:function (e) {
// console.log(this);
},
delay:300
}
}
二、behavior获取组件实例
behavior并不能获取组件实例,他的this指向undefined,因为这时候组件根本没有初始化,这就导致无法在事件中进行this调用到一些方法,最重要的如setData,这就意味在behavior中添加的方法不具备响应式设置数据的能力
所以只能另辟蹊径来进行this的绑定
通过生命周期绑定
我想到了在beihavior的生命周期中可以获取到this,他是指向组件实例的,能够调用到setData
module.exports = Behavior({
lifetimes:{
console.log(this) //指向组件实例
},
}
可是如何将组件实例绑定到behavior添加的事件上呢,生命周期函数无法对调用到methods,无法更改methods方法
起初我想用一个数组存储这些方法,在声明周期中用bind进行绑定,但是发现,在created声明周期中,methods已经生成了,他的更改并不能应用到methods方法中
但是可以使用闭包来巧妙地解决这个事情
我在behavior中对定义的事件进行一次call绑定将事件的this指向一个对象,在闭包的内层函数中,交由声明周期执行,执行函数会将外部用于绑定函数指向的对象属性originThis,指向this实例,这样因为对象的引用,可以在事件中通过this.originThis获取到声明周期中传来的组件实例
definitionFilter(defFields){
defFields.methods.bindDefFields = (function (defFields) {
let _this = {
setData:null
};
let throttleObj= defFields.throttle || {};
let throttleKeyList = Object.keys(throttleObj);
for (let key of throttleKeyList) {
defFields.methods[key] = throttle(throttleObj[key].handler,throttleObj[key].delay,_this);
}
return function () { // 通过声明周期函数调用设置绑定的this对象中的某个this值
_this.origin=this
}
})(defFields)
}
完整的一套节流,绑定组件实例版
const throttle = (fn,delay = 300,_this) => { //节流的逻辑
let time=0;
let ids;
return (...arg) => {
let newTime=Date.now();
if (time < newTime) {
time=newTime+delay;
fn.call(_this,...arg); //将传入的对象进行this绑定
}
if (ids) clearInterval(ids);
ids = setTimeout(() => {
fn.call(_this,...arg)
},delay);
}
}
module.exports = Behavior({ //定义组件扩展
lifetimes:{
created(){ //它的用处在于获取组件实例,传入闭包内层
this.bindDefFields()
}
},
definitionFilter(defFields){
defFields.methods.bindDefFields = (function (defFields) { //创建闭包用于存储绑定对象
let _this = { //创建引用对象用于事件this绑定,不能使用非引用类型,它不具有引用关系
setData:null
};
let throttleObj= defFields.throttle || {};
let throttleKeyList = Object.keys(throttleObj);
for (let key of throttleKeyList) {
defFields.methods[key] = throttle(throttleObj[key].handler,throttleObj[key].delay,_this);
}
return function () { // 通过声明周期函数调用设置绑定的this对象中的某个this值
_this.originThis=this //将引用类型的属性指向这个组件实例
}
})(defFields) //传入组件的数据,但他不是组件实例
}
})
外部组件调用
const dethBehavior = require("../../../../behaviors/debounce-throttle");
Component({
behaviors:[storeBindingsBehavior,dethBehavior],
throttle:{
throttleScroll:{
handler:function (e) { //不能使用箭头函数
console.log(this); //指向组件实例
},
delay:300
}
},
}