Decorator 是一种通过注解表达式就可以扩展类或者方法的函数。Decorator 可以应用到任何一个 class 或者property 上。列如:
@myDecorator class A {} // 作用class @myDecorator doSomething() {} // 作用表达式
Javascript Decorator 目前任然是ES7提案状态,更多该特性的进度可以访问 proposal-decorators 查看。
说到更改对象的属性或者方法,大家肯定会想到 Object.defineProperty(obj, prop, descriptor) 方法,通过该方法,我们可以轻易的修改或者重写对象的行为或者属性,之前 Vue 中提到的双向绑定,即是通过重写 set 和 get 方法来实现的。所以在我们还未正式用上 Decorator 前,都是通过 Object.defineProperty 方法来实现。先来简单的认识下这个方法:
/**
obj : 需要修改属性的对象
prop : 需要修改对象的属性名称
descriptor: 用来定义属性具体行为的描述对象
**/
Object.defineProperty(obj, prop, descriptor)
descriptor 属性说明
configurable : 定义属性对象是否可以被配置,即如果为 false ,定义修改的描述操作(writeable, get 等等)都无效
enumerable : 是否可以通过 for-in 来遍历,或者 Object.keys 列举
value : 定义对象 value 属性的值,value 可以是 number, object, function 等等
writable: 定义 value 值是否可以被重写
get: 一个访问 value 属性时会触发的 function 对象
set: 一个设置 value 属性时会触发的 function 对象
修改一个属性为只读(readonly)
了解 Object.defineProperty 的基本语法后,我通过它先简单实现一个 readonly 实例。具体代码如下:
``javascript # 定义 function myDecoration(target, name, descriptor) {} # 对property使用 class A { @myDecorator test() {} } # 对class使用 @myDecorator class A {} # 带参数 function myDescorator(a) { return function (target, name, descriptor) { console.llog('params:', a) } } @myDescorator(a) class A {} # 时使用多个装饰器(Decorator) @myDecorator1 @myDecorator2 class A {}
利用 Decorator 语法糖修改一个属性为只读(readonly)
我们都知道,在 React 生命周期里有一个 shouldComponentUpdate 方法,该方法通过返回 ture 或者 false 来确定组件是否重新 render 组件。也就是说,通过该方法我们可以过滤掉些无效的数据渲染事件,从而提升性能。例如我们针对 props 传递过来的数据对象进行对比,如果 props 对象的属性以及值并未变更的情况下,则无需执行render方法。
显然通过对比 props 下数据对象的属性与值是否变更,这种逻辑是可以复用的,而不是在单独的在每个组件中去在重复的写 shouldComponentUpdate 方法。说到改变组件对象的方法行为,这里我们显然就可以使用
Decorator 来这个特性来做了,即我们对应用 Decorator 对象的 shouldComponentUpdate 进行重写。通过遍历 props 对象的属性和值,并与老 props 的属性与值进行对比,从而确定是否需要重新渲染。具体代码如下:
function isEqual(a, b) { for (const key in a) { if ({}.hasOwnProperty.call(a, key) && (!{}.hasOwnProperty.call(b, key) || a[key] !== b[key])) { return false; } } for (const key in b) { if ({}.hasOwnProperty.call(b, key) && !{}.hasOwnProperty.call(a, key)) { return false; } } return true; } export default function pureRender(targetComponent) { targetComponent.prototype.shouldComponentUpdate = function (props, state) { return !isEqual(this.state, state) || !isEqual(this.props, props) } } // 使用 @pureRender class ComponentA extends React.Component {}
由于 Decorator 是ES7中的草案,所以现在需要通过 Bable 才能使用。使用方法如下:
安装
npm install --save-dev babel-plugin-transform-decorators
使用
方法一、 通过配置.babelrc
{ "plugins": ["transform-decorators"] }
方法二、通过CLI
babel --plugins transform-decorators script.js
方法三、通过Node API
require("babel-core").transform("code", { plugins: ["transform-decorators"] });
通过 Decorator 这种不需要直接在对象或者方法中编写额外逻辑的方式,就可以轻易的扩展对象或者方法的能力,既满足了功能需求,也精简了代码,保证了代码的可维护性,例如我们已经常见的@log, @test, @mixin等等工具类。所以,以后的工作中可以多多尝试。
细说ES7 JavaScript Decorators
Decorator specification
Exploring EcmaScript Decorators
Object.defineProperty
Babel Legacy Decorator plugin
core-decorators
以上内容就是Decorator 简介及相关教程,希望能帮助到大家。
先关推荐:
以上是Decorator 简介及相关教程的详细内容。更多信息请关注PHP中文网其他相关文章!