欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  后端开发

Decorator 简介及相关教程

程序员文章站 2022-04-03 15:22:23
...

Decorator 简介

Decorator 是一种通过注解表达式就可以扩展类或者方法的函数。Decorator 可以应用到任何一个 class 或者property 上。列如:

@myDecorator class A {} // 作用class

@myDecorator
doSomething() {}  // 作用表达式

Javascript Decorator 目前任然是ES7提案状态,更多该特性的进度可以访问 proposal-decorators 查看。

Decorator原理

说到更改对象的属性或者方法,大家肯定会想到 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 实例。具体代码如下:

Decorator 的基本语法与使用

``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)

利用 Decorator 给 React 组件封装 PureRender

我们都知道,在 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 {}

通过 Babel 使用 Decorator

由于 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 简介及相关教程,希望能帮助到大家。

先关推荐:

JavaScript中函数Decorator实例详解

装饰器decorator详解及实例

php设计模式 Decorator(装饰模式)

以上就是Decorator 简介及相关教程的详细内容,更多请关注其它相关文章!