Javascript 覆盖/扩展React.js中ES7类的静态属性

Javascript 覆盖/扩展React.js中ES7类的静态属性,javascript,inheritance,static,reactjs,ecmascript-2016,Javascript,Inheritance,Static,Reactjs,Ecmascript 2016,ES7引入了静态属性和方法定义的概念。与支持ES7的transpiler一起,它们可以指定道具的验证器和默认值,如下所示: export default class ComponentOne extends React.Component { static propTypes = { foo: React.PropTypes.string } static defaultProps = { foo: 'bar' } // .

ES7引入了
静态
属性和方法定义的概念。与支持ES7的transpiler一起,它们可以指定
道具的验证器和默认值,如下所示:

export default class ComponentOne extends React.Component {
    static propTypes = {
        foo: React.PropTypes.string
    }
    static defaultProps = {
        foo: 'bar'
    }
    // ...
}
这非常方便,但当子类发挥作用时会变得棘手。例如,假设将以下模块添加到与上面的
ComponentOne
相同的代码库中:

export default class ComponentTwo extends ComponentOne {
    static propTypes = {
        baz: React.PropTypes.number
    }
    static defaultProps = {
        baz: 42
    }
    // ...
}
我希望
ComponentTwo
能够“继承”其超类
ComponentOne
的属性验证器和默认值。相反,
ComponentTwo上的
propTypes
defaultProps
ComponentOne
上的属性隐藏起来,React将
ComponentOne
上定义的属性抛出

由于
super
是对当前类的原型的引用,而
static
应该引用直接挂起原型的值,因此我认为这可能会起作用:

import _ from 'lodash';
export default class ComponentTwo extends ComponentOne {
    static propTypes = _.merge(super.propTypes, {
        baz: React.PropTypes.number
    });
}
但是,这会产生一个错误,可能是因为Babel:
解析错误:“super”在函数或类之外

这是可行的,但不是很便于携带:

export default class ComponentTwo extends ComponentOne {
    static propTypes = Object.assign({
        baz: React.PropTypes.number
    }, ComponentOne.propTypes);
}

还有其他更干净/可重用的方法吗?

奇怪的是,使用
super
对静态方法有效。我认为它也应该适用于静态属性。那么,对我来说,直接使用超级类名感觉更自然:

export default class ComponentTwo extends ComponentOne {
  static propTypes = _.merge({}, ComponentOne.propTypes, {
    baz: React.PropTypes.number
  });
}
但是,要使用
super
,我可以想到的一个解决方法是使用静态方法初始化属性,不幸的是,必须手动调用该属性:

class ComponentTwo extends ComponentOne {
  static _init() { 
    this.propTypes = _.merge({}, super.propTypes, {
      baz: React.PropTypes.number
    });
  }
}
ComponentTwo._init();

我偶然发现了这个问题,已经快3年了,但谁知道,可能有人需要它。(这仍然是相关的)

假设在扩展一个类时它会自动继承其父类,那么就不需要覆盖
static propTypes
属性

给定父类:

class Parent {
  static propTypes = {
    parentProp: PropTypes.string
  }
}
如果您不想添加其他道具类型/默认道具,您可以简单地:

class Children extends Parent {
  // Do not declare the propTypes, it will extends by itself.
}
console.log(Children.propTypes); // Will output an object with parentProp in it
如果要明确说明扩展了
Parent
propTypes,或添加了新的propTypes:

class Children extends Parent {
  static propTypes = {
    ...Parent.propTypes, // Yes, you can spread static properties like everything else
    childProp: Proptypes.number,
  }
}
请注意,要使其与Babel正常工作,您可能需要在插件或预设中包含
transform-es2015-classes
Babel插件。我的
.babelrc

"presets": [
  ["env", {
    "include": ["transform-es2015-classes"]
  }],
  "stage-0",
  "react"
],

希望这有帮助

继承具有静态属性的类时,请注意以下注意事项:“如果您是从类继承,那么静态属性将通过
\uuuu proto\uuuu
从类继承,这一点得到广泛支持,但您可能会在使用更旧的浏览器时遇到问题。注意:
\uuuu proto\uuuu
在IE上不受支持。你试过在构造函数中合并
超级.propTypes
吗?@Mat我没有,但是考虑到
props
进入构造函数时已经设置了默认值,我想那太晚了。这不只是我文章末尾建议的重构吗?使用
lodash
而不是
对象。分配
?我的问题是显式引用
ComponentOne
,而不是能够引用“super”类。这没什么大不了的,因为您必须在
extends
语句中引用它,但这并不理想。是的,确实如此,但使用merge的方法是正确的。还添加了另一种选择,我认为更糟糕。您可能可以通过使用静态get propTypes()摆脱ini函数