修饰器(Decorator)是ES7的一个提案,它的出现能解决两个问题:vue
用法也很简单,就是在类或方法的上面加一个@符,在vue in typescript
中常常用到webpack
以上的两个用处可能不太明白,不要紧,咱们开始第一个例子git
@setProp class User {} function setProp(target) { target.age = 30 } console.log(User.age)
这个例子要表达的是对User
类使用setProp
这个方法进行修饰,用来增长User
类中age
的属性,setProp
方法会接收3个参数,咱们如今接触第一个,target
表明User
类自己。github
@setProp(20) class User {} function setProp(value) { return function (target) { target.age = value } } console.log(User.age)
此例和上面功能基本一致,惟一差异在于值是参考修饰函数传过来的web
class User { @readonly getName() { return 'Hello World' } } // readonly修饰函数,对方法进行只读操做 function readonly(target, name, descriptor) { descriptor.writable = false return descriptor } let u = new User() // 尝试修改函数,在控制台会报错 u.getName = () => { return 'I will override' }
上例中,咱们对User
类中的getName
方法使用readonly
修饰器进行修饰,使得方法不能被修改。第一个参数咱们已经知道了,参数name
为方法名,也就是readonly
,参数descriptor
是个啥东西呢,看到这行descriptor.writable = false
,咱们你们猜的也差很少了,这三个参数对应的就是Object.defineProperty
的三个参数,咱们来看一下:typescript
咱们设置descriptor.writable = false
就是让函数不能够被修改,若是咱们写成编程
descriptor.value = 'function (){ console.log('Hello decorator') }'
那么,输出就是Hello World
了,而是Hello decorator
,是否是已经意识到修饰器的好处了。如今咱们来看看实际工做中,咱们用到修饰器的例子json
在用webpack
打包时,咱们常常须要好多步骤,好比第一步读取package.json
文件,第二步处理该文件,第三步加载webpack.base.js
文件,第四步进行打包...为了直观,咱们常常在每一步打印一些日志文件,好比这步都干了些什么事,很明显打印日志的操做和业务代码根本就一点关系没有,咱们不该该把日志和业务掺和在一块儿,这样使用修饰器就是避免这个问题,如下为代码:app
class Pack { @log('读取package.json文件') step1() { // do something... // 没有修饰器以前,咱们一般把console.log放到这里写 // 放到函数里面写会有两个坏处 // 1.console和业务无关,会破坏函数单一性原则 // 2.若是要删除全部的console,那咱们只能深刻到每个方法中 } @log('合并webpack配置文件') step2() { // do something... } } function log(value) { return function (target, name, descriptor) { // 在这里,咱们还能够拿到函数的参数,打印更加详细的信息 console.log(value) } } let pack = new Pack() pack.step1() pack.step2()
这个例子在实际的开发中经常使用获得,咱们一些操做前,必须得判断用户是否登陆,比较点赞、结算、发送弹幕...按照以前的写法,咱们必须在每个方法中判断用户的登陆状况,而后再进行业务的操做,很显然前置条件和业务又混到了一块儿,用修饰器,就能够完美的解决这一问题,代码以下:ide
class User { // 获取已登陆用户的用户信息 @checkLogin getUserInfo() { /** * 以前,咱们都会这么写: * if(checkLogin()) { * // 业务代码 * } * 这段代码会在每个须要登陆的方法中执行 * 仍是上面的问题,执行的前提和业务又混到了一块儿 */ console.log('获取已登陆用户的用户信息') } // 发送消息 @checkLogin sendMsg() { console.log('发送消息') } } // 检查用户是否登陆,若是没有登陆,就跳转到登陆页面 function checkLogin(target, name, descriptor) { let method = descriptor.value // 模拟判断条件 let isLogin = true descriptor.value = function (...args) { if (isLogin) { method.apply(this, args) } else { console.log('没有登陆,即将跳转到登陆页面...') } } } let u = new User() u.getUserInfo() u.sendMsg()
以上只是修饰器的基本应用,只要咱们掌握了原理,在实际的工做中,要思考本身的应用场景,只要咱们涉及须要在执行前作一些处理的应用,不论是修改函数的参数值,仍是增长属性,仍是执行的先决条件,咱们均可以使用修饰器,这种编程的方式,就是面向切面编程