摘要:例子修饰类自定义参数值此例和上面功能基本一致,唯一差别在于值是参考修饰函数传过来的例子修饰方法修饰函数,对方法进行只读操作尝试修改函数,在控制台会报错上例中,我们对类中的方法使用修饰器进行修饰,使得方法不能被修改。
什么是修饰器
修饰器(Decorator)是ES7的一个提案,它的出现能解决两个问题:
不同类间共享方法
编译期对类和方法的行为进行改变
用法也很简单,就是在类或方法的上面加一个@符,在vue in typescript中经常用到
以上的两个用处可能不太明白,没关系,我们开始第一个例子
例子1:修饰类</>复制代码
@setProp
class User {}
function setProp(target) {
target.age = 30
}
console.log(User.age)
这个例子要表达的是对User类使用setProp这个方法进行修饰,用来增加User类中age的属性,setProp方法会接收3个参数,我们现在接触第一个,target代表User类本身。
例子2:修饰类(自定义参数值)</>复制代码
@setProp(20)
class User {}
function setProp(value) {
return function (target) {
target.age = value
}
}
console.log(User.age)
此例和上面功能基本一致,唯一差别在于值是参考修饰函数传过来的
例子2:修饰方法</>复制代码
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的三个参数,我们来看一下:
我们设置descriptor.writable = false就是让函数不可以被修改,如果我们写成
</>复制代码
descriptor.value = "function (){ console.log("Hello decorator") }"
那么,输出就是Hello World了,而是Hello decorator,是不是已经意识到修饰器的好处了。现在我们来看看实际工作中,我们用到修饰器的例子
实际应用1:日志管理在用webpack打包时,我们经常需要好多步骤,比如第一步读取package.json文件,第二步处理该文件,第三步加载webpack.base.js文件,第四步进行打包...为了直观,我们经常在每一步打印一些日志文件,比如这步都干了些什么事,很明显打印日志的操作和业务代码根本就一点关系没有,我们不应该把日志和业务掺和在一起,这样使用修饰器就是避免这个问题,以下为代码:
</>复制代码
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()
实际应用2:检查登录
这个例子在实际的开发中常用得到,我们一些操作前,必须得判断用户是否登录,比较点赞、结算、发送弹幕...按照之前的写法,我们必须在每一个方法中判断用户的登录情况,然后再进行业务的操作,很显然前置条件和业务又混到了一起,用修饰器,就可以完美的解决这一问题,代码如下:
</>复制代码
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()
结语
以上只是修饰器的基本应用,只要我们掌握了原理,在实际的工作中,要思考自己的应用场景,只要我们涉及需要在执行前做一些处理的应用,不管是修改函数的参数值,还是增加属性,还是执行的先决条件,我们都可以使用修饰器,这种编程的方式,就是面向切面编程
源码以及使用方法,请移步GitHub文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/88933.html
摘要:修饰器是一个函数,用于修改类行为。结论以上只是一个很简单的修饰器示例,你可以根据需要生产一些有意思的修饰器,让编写的代码更优雅更干净。 一般在JavaScript中为了让部分代码延迟执行,一想起的自然是 setTimeout,比如: setTimeout(() => { // doing }, 0); 这种代码或许你不知道写过多少遍,但,我们在 setTimeout 中多数情况下会...
摘要:下装饰者的实现了解了装饰者模式和的概念之后,我们写一段能够兼容的代码来实现装饰者模式原函数拍照片定义函数装饰函数加滤镜用装饰函数装饰原函数这样我们就实现了抽离拍照与滤镜逻辑,如果以后需要自动上传功能,也可以通过函数来添加。 showImg(https://segmentfault.com/img/bVbueyz?w=852&h=356); 什么是装饰者模式 当我们拍了一张照片准备发朋友...
ES6 Decorators(修饰器) 修饰器(Decorator)是一个函数,用来修改类的行为。这是ES7的一个提案,目前Babel转码器已经支持 我们在游戏大型项目种经常会用到的方法,现在es6直接支持 想要使用Decorator的话需要我们配置一下文件夹,配置一下环境 npm install babel-plugin-transform-decorators-legacy --save-de...
摘要:前言今天闲来时看了看中的新标准之一,装饰器。过程中忽觉它和中的注解有一些类似之处,并且当前版本的中已经支持它了,所以,就动手在一个应用中尝鲜初体验了一番。另外,由于装饰器目前还是中的一个提案,其中具体细节可能还会更改。 前言 今天闲来时看了看ES7中的新标准之一,装饰器(Decorator)。过程中忽觉它和Java中的注解有一些类似之处,并且当前版本的TypeScript中已经支持它了...
摘要:为了代码进一步解耦,可以考虑使用高阶组件这种模式。开源的高阶组件使用提供了一系列使用的高阶组件,可以增强组件的行为,可以利用此库学习高阶组件的写法。通过使用此库提供的高阶组件,可以方便地让列表元素可拖动。 1. Decorator基本知识 在很多框架和库中看到它的身影,尤其是React和Redux,还有mobx中,那什么是装饰器呢。 修饰器(Decorator)是一个函数,用来修改类的...
阅读 973·2021-09-07 09:58
阅读 1533·2021-09-07 09:58
阅读 2924·2021-09-04 16:40
阅读 2533·2019-08-30 15:55
阅读 2466·2019-08-30 15:54
阅读 1398·2019-08-30 15:52
阅读 466·2019-08-30 10:49
阅读 2634·2019-08-29 13:21