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;
  }

}

posted @ 2019-05-26 22:43  hid3onbush  阅读(307)  评论(0编辑  收藏  举报