title: 使用子类 sidebar_label: 使用子类

hide_title: true

使用子类

对使用子类的支持是有限制的。 最值得注意的一点是你只能重新定义原型中的 actions/flows/computeds——你不能重新定义字段声明。 在子类中请使用 override 注释被重新定义的methods/getters - 见下例。 请凡事从简,并优先考虑组合(而非继承)。

  1. import { makeObservable, observable, computed, action } from "mobx"
  2. class Parent {
  3. // 被注释的实例字段不可被重新定义
  4. observable = 0
  5. arrowAction = () => {}
  6. // 未被注释的实例字段可以被重新定义
  7. overridableArrowAction = action(() => {})
  8. // 被注释的原型methods/getters可以被重新定义
  9. action() {}
  10. actionBound() {}
  11. get computed() {}
  12. constructor(value) {
  13. makeObservable(this, {
  14. observable: observable,
  15. arrowAction: action
  16. action: action,
  17. actionBound: action.bound,
  18. computed: computed,
  19. })
  20. }
  21. }
  22. class Child extends Parent {
  23. /* --- 继承来的定义 --- */
  24. // 抛出 - TypeError: Cannot redefine property
  25. // observable = 5
  26. // arrowAction = () = {}
  27. // OK - 未被注释的
  28. overridableArrowAction = action(() => {})
  29. // OK - 原型
  30. action() {}
  31. actionBound() {}
  32. get computed() {}
  33. /* --- 新的定义 --- */
  34. childObservable = 0;
  35. childArrowAction = () => {}
  36. childAction() {}
  37. childActionBound() {}
  38. get childComputed() {}
  39. constructor(value) {
  40. super()
  41. makeObservable(this, {
  42. // 继承来的
  43. action: override,
  44. actionBound: override,
  45. computed: override,
  46. // 新的
  47. childObservable: observable,
  48. childArrowAction: action
  49. childAction: action,
  50. childActionBound: action.bound,
  51. childComputed: computed,
  52. })
  53. }
  54. }

Limitations

  1. 只有定义在原型上的 action, computed, flow, action.bound 可以在子类中被重新定义
  2. 不能在子类中重新注释字段(override 除外)。
  3. makeAutoObservable 不支持在子类中使用。
  4. 不支持扩展内置数据结构(ObservableMap, ObservableArray, 等)。
  5. 你不能在子类中给makeObservable提供不同选项。
  6. 你不能在单个继承链中混合使用注解/装饰器。
  7. 所有其他限制均在此适用

TypeError: Cannot redefine property

如果你遇到这一错误, 你可能正在子类中重新定义箭头函数x = () => {}。 其不可行的原因是一切被注释的类字段都是不可配置的(详见限制)。 你有以下这两个选择:

1. 将函数移至原型并使用action.bound注释 javascript class Parent { // action = () => {}; // => action() {} constructor() { makeObservable(this, { action: action.bound }) } } class Child { action() {} constructor() { super() makeObservable(this, { action: override }) } }
2. 移除action注释并手动将函数包装于action里:x = action(() => {}) javascript class Parent { // action = () => {}; // => action = action(() => {}) constructor() { makeObservable(this, {}) // <-- 注释已被移除 } } class Child { action = action(() => {}) constructor() { super() makeObservable(this, {}) // <-- 注释已被移除 } }