带有 React 组件的装饰器
Decorators with React Components
我对能够使用 @myDecorator
语法(使用 babel)感到非常兴奋。我正在尝试装饰生命周期函数之一,特别是 componentWillMount
,并检查装饰器中组件的 props
和 context
。但是,我似乎无法访问 props
或 context
。我不确定这是否是一种反模式,或者我只是在做这个错误。
小例子:
// TestComponent.jsx
import checkProps from 'checkProps.js';
class TestComponent extends React.Component {
@checkProps
componentWillMount() {
// Do something.
}
render() {
return <div>My Component</div>
}
}
和
// checkProps.js
export function checkProps(target) {
console.log(target.props);
}
我也尝试过装饰器的箭头函数并检查 this
,但我认为装饰器不会以这种方式组合东西。
我也试过让我的装饰器成为工厂并传入 this.props
和 this.context
但是 this
在装饰组件生命周期函数时未定义。
ES7 ECMAScript 装饰器有 the same API as Object.defineProperty(target, name, descriptor)
所以 target
参数是你的 class 在你的装饰器应用时,而不是在它被 React
调用的时间。要影响装饰器在运行时所做的事情,您必须修改 descriptor.value
这是装饰的实际功能:
export function checkProps(target, name, descriptor) {
// Save the original method, it'd be a good idea
// to check that it really is a function
const decoratee = descriptor.value;
// Modify the descriptor to return our decorator
// function instead of the original
descriptor.value = function decorated(...args) {
// Do something before ...
console.log('before: ' + name, this.props, args);
// Calling the decorated method on this object
// with some arguments that could have been
// augmented by this decorator
decoratee.apply(this, args);
// Do something after ...
console.log('after: ' + name);
};
}
// Or if you wanted to use a factory function to supply some configuration
// to the decorator you can do it this way
export function checkProps(config) {
return function configurableCheckProps(target, name, descriptor) {
// Save the original method, it'd be a good idea
// to check that it really is a function
const decoratee = descriptor.value;
if (config.someOption) {
// Do something based on the config
}
// Modify the descriptor to return our decorator
// function instead of the original
descriptor.value = function decorated(...args) {
// Do something before ...
console.log('before: ' + name, this.props, args);
if (config.someOption) {
// Do something based on the config
}
// Calling the decorated method on this object
// with some arguments that could have been
// augmented by this decorator
decoratee.apply(this, args);
// Do something after ...
console.log('after: ' + name);
};
};
}
这里 an example that also modifies the behavior of a method 更彻底地展示了这一点。
希望这对您有所帮助。编码愉快!
编辑:正如评论者指出的那样,装饰器不是 ES7 的一部分,但截至 2016 年 3 月 the proposal is still in Stage 1,我的错
EDIT2:截至 2018 年 6 月,提案已在 the proposal is still in Stage 2 中,我们越来越接近
我对能够使用 @myDecorator
语法(使用 babel)感到非常兴奋。我正在尝试装饰生命周期函数之一,特别是 componentWillMount
,并检查装饰器中组件的 props
和 context
。但是,我似乎无法访问 props
或 context
。我不确定这是否是一种反模式,或者我只是在做这个错误。
小例子:
// TestComponent.jsx
import checkProps from 'checkProps.js';
class TestComponent extends React.Component {
@checkProps
componentWillMount() {
// Do something.
}
render() {
return <div>My Component</div>
}
}
和
// checkProps.js
export function checkProps(target) {
console.log(target.props);
}
我也尝试过装饰器的箭头函数并检查 this
,但我认为装饰器不会以这种方式组合东西。
我也试过让我的装饰器成为工厂并传入 this.props
和 this.context
但是 this
在装饰组件生命周期函数时未定义。
ES7 ECMAScript 装饰器有 the same API as Object.defineProperty(target, name, descriptor)
所以 target
参数是你的 class 在你的装饰器应用时,而不是在它被 React
调用的时间。要影响装饰器在运行时所做的事情,您必须修改 descriptor.value
这是装饰的实际功能:
export function checkProps(target, name, descriptor) {
// Save the original method, it'd be a good idea
// to check that it really is a function
const decoratee = descriptor.value;
// Modify the descriptor to return our decorator
// function instead of the original
descriptor.value = function decorated(...args) {
// Do something before ...
console.log('before: ' + name, this.props, args);
// Calling the decorated method on this object
// with some arguments that could have been
// augmented by this decorator
decoratee.apply(this, args);
// Do something after ...
console.log('after: ' + name);
};
}
// Or if you wanted to use a factory function to supply some configuration
// to the decorator you can do it this way
export function checkProps(config) {
return function configurableCheckProps(target, name, descriptor) {
// Save the original method, it'd be a good idea
// to check that it really is a function
const decoratee = descriptor.value;
if (config.someOption) {
// Do something based on the config
}
// Modify the descriptor to return our decorator
// function instead of the original
descriptor.value = function decorated(...args) {
// Do something before ...
console.log('before: ' + name, this.props, args);
if (config.someOption) {
// Do something based on the config
}
// Calling the decorated method on this object
// with some arguments that could have been
// augmented by this decorator
decoratee.apply(this, args);
// Do something after ...
console.log('after: ' + name);
};
};
}
这里 an example that also modifies the behavior of a method 更彻底地展示了这一点。
希望这对您有所帮助。编码愉快!
编辑:正如评论者指出的那样,装饰器不是 ES7 的一部分,但截至 2016 年 3 月 the proposal is still in Stage 1,我的错
EDIT2:截至 2018 年 6 月,提案已在 the proposal is still in Stage 2 中,我们越来越接近