javascript - 如何创建一个向组件类添加单个函数的装饰器?

标签 javascript reactjs decorator ecmascript-next

我应该先说我对 es7 装饰器知之甚少。基本上我想要的是一个名为 @model 的装饰器,它将一个函数添加到名为 model 的组件中。例如,我会这样调用它

@model class FooBar extends Component { }

然后 FooBar 类现在将具有模型函数。

这是我尝试过的:

Model.js

export default function reactModelFactory( ctx ){

    return (key)=>{
        return {
            onChange: (e)=>ctx.setState({[key]:e.target.value}),
            value: ctx.state[key],
            name: key
        };
    };

};

function modelDecorator() {
    return function(ctx){
        return class extends ctx{
            constructor(...args){
                super(...args);
                this.model = reactModelFactory(this);
            }
        }
    }
}

export { modelDecorator as model };

Login.js

import React,{PureComponent} from 'react';
import {model} from './Model';

@model class Login extends PureComponent{}

React 抛出错误消息:

TypeError: Super expression must either be null or a function, not object

我不知道这意味着什么。我正在寻求一些帮助来让我的装饰器工作,而额外的好处是完全理解装饰器的概念。

最佳答案

要添加@dfsq的答案(我假设它满足您的要求),您可以通过将 model() 添加到 prototype 来在界面性能方面更进一步 而不是像这样的每个实例:

export default function reactModelFactory() {
  return function model (key) {
    return {
      onChange: (e) => this.setState({ [key]: e.target.value }),
      value: this.state[key],
      name: key
    };
  };
};

function modelDecorator(Class) {
  Object.defineProperty(Class.prototype, 'model', {
    value: reactModelFactory(),
    configurable: true,
    writable: true
  });

  return Class;
}

这对于性能来说要好得多,因为它会导致装饰器使用 model 成员方法一次修改现有类的 prototype ,而不是附加一个作用域副本每次构造新实例时,匿名扩展类的构造函数中的model方法。

澄清一下,这意味着在 @dfsq 的答案中,每次构造新实例时都会调用 reactModelFactory() ,而在此答案中, reactModelFactory() 是仅在类上激活装饰器时调用一次。

我在property descriptor中使用可配置可写的原因是因为这就是 class { } 语法在 prototype 上原生定义成员方法的方式:

class Dummy {
  dummy () {}
}

let {
  configurable,
  writable,
  enumerable
} = Object.getOwnPropertyDescriptor(Dummy.prototype, 'dummy');

console.log('configurable', configurable);
console.log('enumerable', enumerable);
console.log('writable', writable);

关于javascript - 如何创建一个向组件类添加单个函数的装饰器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48428830/

相关文章:

.net - 在 Windsor 中注册通用装饰器

python - 同时使用带参数和不带参数的装饰器

javascript - 随机图像生成器但从不重复相同的图像 - Javascript

javascript - Controller 中方法的未定义局部变量或方法 `env'

javascript - 自动执行 HTTP 请求

javascript - useEffect 钩子(Hook)在初始渲染时调用,无需更改依赖项

python - 如何将装饰器附加到 python 中的函数 "after the fact"?

javascript - 如何在设置 dangerouslysetinnerHtml 时从 ReactJS 中的 html 字符串呈现 react 组件?

javascript - 如何使用react路由链接将参数传递给组件

javascript - 通过react-router处理带有斜杠的路径的方法是什么?