js-使用装饰器去抖


  • 装饰器装饰类

    修改类了的行为,为它添加了静态属性zs。

function test (target) {
  target.zs = true;
}

@test
class App {}

App.zs // true
  • 装饰器装饰类的方法

    装饰类的方法与Object.defineProperty有些许类似。

function test (target, key, descriptor) {
  /*
  * ...do something for descriptor...
  */
  return descriptor;
}


class App {

  @test
  sayHi(){}

}

装饰器的应用

import { debounce } from './utils.js';

class App extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      count: 1,
    };
    this.handleClick = this.handleClick.bind(this);
  }

  /*
  * 装饰器可以装饰类和类的方法,需要注意的是装饰方法是原型对象方法
  * no fn(){}
  * ok fn = () => {}
   */
  @debounce(200)
  handleClick() {
    this.setState({ count: this.state.count + 1 });
  }


  render() {
    return (
      <div>
        <button onClick={this.handleClick}>add-click</button>
        <p>{this.state.count}</p>
      </div>
    )
  }
}

export default App;
utils.js

/**
 * 去抖
 * @param {Number} timeout
 */
export function debounce(timeout) {

  // https://segmentfault.com/a/1190000015970099
  // return function (target, key, descriptor) {
  //   // 创建一个Map的数据结构,将实例化对象作为key
  //   const instanceMap = new Map();
  //   return Object.assign({}, descriptor, {
  //     value() {
  //       // 清除延时器
  //       clearTimeout(instanceMap.get(this));
  //       // 设置延时器
  //       instanceMap.set(this, setTimeout(() => {
  //         // 调用该方法
  //         // descriptor.value.call(this, ...arguments);
  //         descriptor.value.apply(this, arguments);
  //         // 将延时器设置为 null
  //         instanceMap.set(this, null);
  //       }, timeout));
  //     }
  //   });
  // }

  // 简单实现去抖
  /*
  descriptor与Object.defineProperty的第三个参数相等
  相当于劫持了这个对象中的一个属性,但这个属性值是一个方法。
  eg:
  var student = {
    age: 14,
    sayHi: function (name) {
      console.log('hi~' + name);
    }
  }
  const fn = student.sayHi;
  Object.defineProperty(student, 'sayHi', {
    configurable: true,
    enumerable: true,
    writable: true,
    value() {
      setTimeout(() => {
        // 不能在此复制方法,会引起爆栈 const fn = st..Hi;
        console.log('重写当前方法');
        fn.apply(this, arguments)
      }, 2000)
    }
  })
   */

  return function (target, key, descriptor) {
    // 获取被装饰的方法
    const oldValue = descriptor.value;
    // 初始timerID
    let timer = null;
    // 覆盖被装饰的方法
    descriptor.value = function () {
      clearTimeout(timer);
      timer = setTimeout(() => {
        oldValue.apply(this, arguments)
      }, timeout);
    };
    return descriptor;
  }

}
优质内容筛选与推荐>>
1、知名互联网公司网站架构图
2、IOS 四种保存数据的方式
3、BestCoder17 1001.Chessboard(hdu 5100) 解题报告
4、hdu1712 ACboy needs your help(分组背包)
5、JPA基础(七):使用JPA加载_更新_删除对象


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号