微信小程序behavior定义事件绑定this指向-节流示例

一、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
        }
    },
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值