覆盖React组件的原型方法

时间:2017-04-13 18:38:21

标签: javascript reactjs

我们说我有以下React Component类:

class SayHello extends React.Component {
    constructor(props) {
        super(props);

        this.handleOnClick = this.handleOnClick.bind(this);
    }

    render() {
        return <div onClick={this.handleOnClick}>Click Me</div>;
    }

    handleOnClick() {
        console.log("clicked");
    }
}

我想要做的是创建一个更高阶的组件,该组件知道handleOnClick中的SayHello,但之前调用SayHello&#39; s { {1}},我希望它能够执行我先传入的一些代码(即我想运行在我的服务器中记录某些内容的代码)。

是否有React模式可以做这样的事情?

修改

我想在这里提供更多背景信息。我希望我的高阶组件在调用哪些方法时是动态的。例如,有时它可能是handleOnClick,但有时可能是handleOnClick

2 个答案:

答案 0 :(得分:5)

higher-order component是一个接受组件参数并返回新组件的函数。

此函数返回一个带有装饰handleClick方法的组件:

// A higher-order component that runs some code before
// the given component's `handleClick` method
function wrapHello(componentClass) {
  return class wrapped extends componentClass {
    beforeHandleClick() {
      console.log("I run first!")
    }

    handleClick(...args) {
      this.beforeHandleClick()
      super.handleClick(...args)
    }
  }
}

This pattern很整洁,因为它根本不属于React;它只是pure function。这意味着它易于测试和推理。

这是一个没有使用React的测试工具:

&#13;
&#13;
function wrapHello(componentClass) {
  return class wrapped extends componentClass {
    beforeHandleClick() {
      console.log("I run first!")
    }

    handleClick(...args) {
      this.beforeHandleClick()
      super.handleClick(...args)
    }
  }
}

class SayHello {
  handleClick() {
    console.log("handleClick")
  }
}

const WrappedHello = wrapHello(SayHello)
new WrappedHello().handleClick()
&#13;
&#13;
&#13;

答案 1 :(得分:2)

你需要像动态mixin这样的东西。

这个高阶组件采用Component类和装饰器方法的对象。

HOC包装每个具有匹配装饰器的方法。这些方法调用装饰器然后调用原始组件方法。非装饰方法不变。

str.split(" ").toList.map { s => 
  if(replacements.get(s).isDefined) { 
    replacements(s) 
  } else { 
    s  
  } 
}.mkString(" ")

在这种情况下,装饰器方法与基类方法名称完全匹配。如果你想要装饰器使用,例如相反,// Higher-order component function decorateMethods(componentClass, decorators) { class decoratedClass extends componentClass { } Object.keys(decorators).forEach(decoratorName => { decoratedClass.prototype[decoratorName] = function(...args) { decorators[decoratorName].call(this, ...args); return componentClass.prototype[decoratorName].call(this, ...args) } }) return decoratedClass } // // Test // class Component { foo() { console.log("foo") } bar() { console.log("bar") } baz() { console.log("baz") } } const DecoratedComponent = decorateMethods(Component, { foo() { console.log("before foo") }, bar() { console.log("before bar") } }) const d = new DecoratedComponent() d.foo() d.bar() d.baz()可以使用以下方法映射方法名称:

beforeFoo