如何(不)使用装饰器

如何(不)使用装饰器

在MobX 中使用 ES.next 装饰器是可选的。本章节将解释如何(避免)使用它们。

使用装饰器语法的优势:

  • 样板文件最小化,声明式代码。

使用装饰器语法的劣势:

  • ES.next 2阶段特性。

在 MobX 中使用装饰器有两种方式。

  • 开启编译器的实验性装饰器语法 (详细请参见下面)

使用装饰器语法:

import { observable, computed, action } from "mobx"; class Timer { @observable start = Date.now( @observable current = Date.now( @computed get elapsedTime() { return this.current - this.start + "milliseconds"; } @action tick() { this.current = Date.now( } } Copy

使用 decorate 工具:

import { observable, computed, action } from "mobx"; class Timer { start = Date.now( current = Date.now( get elapsedTime() { return this.current - this.start + "milliseconds"; } tick() { this.current = Date.now() } } decorate(Timer, { start: observable, current: observable, elapsedTime: computed, tick: action }) Copy

注意, mobx-react 中的 observer 函数既是装饰器又是函数,这意味着下面这些语法都可以正常运行:

@observer class Timer extends React.Component { /* ... */ } const Timer = observer(class Timer extends React.Component { /* ... */ }) const Timer = observer((props) => ( /* 渲染 */ )) Copy

启用装饰器语法

如果想使用装饰器,需要按照下列步骤。

TypeScript

tsconfig.json 中启用编译器选项 "experimentalDecorators": true

Babel: 使用 babel-preset-mobx

另外一种在 Babel 中配置 MobX 的方式是使用 mobx preset,这种方式更方便,其中包含了装饰器及其他几个经常与 mobx 一起使用的插件:

npm install --save-dev babel-preset-mobx Copy

.babelrc:

{ "presets": ["mobx"] } Copy

Babel: 手动启用装饰器

要启用装饰器的支持而不使用 mobx preset 的话,需要按照下列步骤。 安装支持装饰器所需依赖: npm i --save-dev babel-plugin-transform-decorators-legacy 。 并在 .babelrc 文件中启用:

{ "presets": ["es2015", "stage-1"], "plugins": ["transform-decorators-legacy"] } Copy

注意,插件的顺序很重要: transform-decorators-legacy 应该放在首位。 babel 设置有问题?请先参考这个 issue 。

对于 babel 7, 参见 issue 1352 来查看设置示例。

装饰器语法 和 Create React App

  • create-react-app 目前还没有内置的装饰器支持。要解决这个问题,你可以使用 eject 命令 或使用 react-app-rewired。

免责声明: 装饰器语法的局限性:

当前编译器所实现的装饰器语法是有一些限制的,而且与实际的装饰器语法表现并非完全一致。 此外,在所有编译器都实现第二阶段的提议之前,许多组合模式目前都无法与装饰器一起使用。 由于这个原因,目前在 MobX 中对装饰器语法支持的范围进行了限定,以确保支持的特性在所有环境中始终保持一致。

MobX 社区并没有正式支持以下模式:

  • 重新定义继承树中的装饰类成员

在第一次读/写到装饰属性之前,该属性在类实例上可能是不可见的。

(注意: 不支持并不意味着不能运行,它的意义在于如果不能正常运行的话,在官方规范的推进之前,提出的 issues 是不会被处理的。)