Angular装饰器详解(一) - 前言篇1

100 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第14天,点击查看活动详情

Angular中大量使用了装饰器,有Component装饰器,Module装饰器,有Input装饰器,方法装饰器,属性装饰器等。而且还可以自定义装饰器。本系列文章会和大家一起来感受装饰器的美。

装饰器

修饰器是ES7加入的新特性,修饰器实际上就是设计模式中常说的装饰者模式的一种实现。在ES6开始,设计模式原生化就已经是非常明显的趋势了,无论是for..of..Iterator接口的配合内化了迭代者模式,Proxy对象实现的代理模式等等,都可以看出Javascript逐渐走向标准化的趋势和决心。

装饰器模式

装饰器模式(Decorator Pattern),是指在不必改变原类文件或使用继承的情况下,动态地扩展一个对象的功能,为对象增加额外特性的一种设计模式。它允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。

装饰器就是为了解决在不修改原本组件、接口或者类的时候为其添加额外的功能。

  • 从本质上看,装饰器模式是一个包装模式((Wrapper Pattern),它是通过封装其他对象达到设计的目的;
  • 从结果的角度来看,使用装饰器和直接修改类的定义没有什么区别,但使用装饰器更符合开放封闭原则,且更符合声明式的思想;

由于ES7中已经可以使用装饰器了,我们先慢慢来哈,先来了解一下ES7中的装饰器。

ES7的装饰器

装饰器目前还处于草稿阶段,不过可以先来了解一下。

装饰器可以装饰四种类型的值:

  1. 类;
  2. 类的属性;
  3. 类的方法;
  4. 属性存取器;

class装饰器

装饰器的本质是一种函数,写成 @ + 函数名。

@addSkill
class Person { }

function addSkill(target) {
    target.say = "hello world"; //直接添加到类中
    target.prototype.eat = "apple"; //添加到类的原型对象中
}
var personOne = new Person();

console.log(Person['say']); // 'hello world'
console.log(personOne['eat']); // 'apple'

如果在class上添加一个装饰器,发现在浏览器中是无法直接运行的,浏览器对于这种语法糖还不支持。如果要想使用它,还需要提前做一些准备工作,对它进行编译。

  • 安装插件;
npm i babel-plugin-transform-decorators-legacy babel-register --save-dev
  • 创建compile.js文件
const babel = require('babel-register');

babel({
    plugins: ['transform-decorators-legacy']
});

require('./app.js');
  • app文件
@addSkill
class Person { }

function addSkill(target) {
    target.say = "hello world"; //直接添加到类中
    target.prototype.eat = "apple"; //添加到类的原型对象中
}
var personOne = new Person();

console.log(Person['say']); // 'hello world'
console.log(personOne['eat']); // 'apple'
  • 执行compile.js

装饰器还可以带参数:

@addSkill('I love')
class Person { }

function addSkill(msg) {
    return function(target){
        target.prototype.eat = msg + ' ' + "apple";
    }
}
var personOne = new Person();

console.log(personOne.eat);

上面的例子中,由于装饰器要携带参数,addSkill('I love')必须返回一个函数,所以,addSkill就是一个函数的函数。

本文,我们先从整体上介绍了解了什么是装饰器,以及装饰器模式,和ES7中Class装饰器。后续文章,会继续分享这一部分哦。