- log
为一个方法添加 log 函数,检查输入的参数:
class Math {
@log
add(a, b) {
return a + b;
}
}
function log(target, name, descriptor) {
var oldValue = descriptor.value;
descriptor.value = function(...args) {
console.log(`Calling ${name} with`, args);
return oldValue.apply(this, args);
};
return descriptor;
}
const math = new Math();
// Calling add with [2, 4]
math.add(2, 4);
- debounce
有的时候,我们需要对执行的方法进行防抖处理:
class Toggle extends React.Component {
@debounce(500)
handleClick() {
console.log('toggle')
}
render() {
return (
<button onClick={this.handleClick}>
button
</button>
);
}
}
我们来实现一下:
function _debounce(func, wait) {
var timeout;
return function () {
var context = this;
var args = arguments;
if (timeout) clearTimeout(timeout);
timeout = setTimeout(function(){
func.apply(context, args)
}, wait);
}
}
function debounce(wait) {
return function handleDescriptor(target, key, descriptor) {
const callback = descriptor.value;
var fn = _debounce(callback, wait)
return {
...descriptor,
value:fn
};
}
}
- time
用于统计方法执行的时间:
function time(prefix) {
return function handleDescriptor(target, key, descriptor) {
const fn = descriptor.value;
if (prefix == null) {
prefix = `${target.constructor.name}.${key}`;
}
return {
...descriptor,
value() {
const label = `${prefix}-${count}`;
console.time(label);
fn.apply(this, arguments);
console.timeEnd(label);
}
}
}
}
- mixin
用于将对象的方法混入 Class 中:
const SingerMixin = {
sing(sound) {
alert(sound);
}
};
const FlyMixin = {
get speed() {},
fly() {},
land() {}
};
@mixin(SingerMixin, FlyMixin)
class Bird {
singMatingCall() {
this.sing('tweet tweet');
}
}
var bird = new Bird();
bird.singMatingCall();
// alerts "tweet tweet"
mixin 的一个简单实现如下:
function mixin(...mixins) {
return target => {
for (let i = 0, l = mixins.length; i < l; i++) {
const descs = Object.getOwnPropertyDescriptors(mixins[i]);
const keys = Object.getOwnPropertyNames(descs);
for (let j = 0, k = keys.length; j < k; j++) {
const key = keys[j];
if (!target.prototype.hasOwnProperty(key)) {
Object.defineProperty(target.prototype, key, descs[key]);
}
}
}
};
}
- redux
实际开发中,React 与 Redux 库结合使用时,常常需要写成下面这样。
class MyReactComponent extends React.Component {}
export default connect(mapStateToProps, mapDispatchToProps)(MyReactComponent);
有了装饰器,就可以改写上面的代码。
@connect(mapStateToProps, mapDispatchToProps)
export default class MyReactComponent extends React.Component {};
相对来说,后一种写法看上去更容易理解。
完结撒花,有问题留言讨论哈~~~