- 装饰器装饰类
修改类了的行为,为它添加了静态属性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;
}
}