装饰器函数(详解如何在JavaScript中使用装饰器)
导读:Decorator装饰器是ES7的时候提案的特性,目前处于Stage 3候选阶段(2022年10月)。...
Decorator装饰器是ES7的时候提案的特性,目前处于Stage 3候选阶段(2022年10月)。
装饰器简单来说就是修改类和类方法的语法糖,很多面向对象语言都有装饰器这一特性。
为了使用装饰器特性,我们需要用进行babel转义。这里需要用到的是@babel/plugin-proposal-decorators。
安装
npm install --save-dev @babel/plugin-proposal-decorators
vite配置
import { defineConfig } from vite;
import babel from vite-plugin-babel;
export default defineConfig({
plugins: [
babelDev({
babelConfig: {
plugin: [@babel/plugin-proposal-decorators]
}
}),
// ...
],
// ...
})
webpack配置
module: {
rules: [
{
test: /\.(js|mjs|jsx|ts|tsx)$/,
use: {
loader: babel-loader,
options: {
// ...
plugins: [
[@babel/plugin-proposal-decorators, { legacy: true }],
// ...
],
// ...
},
}
// ...
}
]
}
使用
先来一图了解装饰器语法。
语法: @+函数名
@frozen
class Foo {
@throttle(500)
expensiveMethod() {}
}
类装饰器
参数target是类本身
function testable(target) {
target.isTestable = true;
}
@testable
class MyTestableClass {
// ...
}
MyTestableClass.isTestable // true
带参数的修饰器
@+返回装饰器函数的表达式
function testable(isTestable) {
return function(target) {
target.isTestable = isTestable;
}
}
@testable(true)
class MyTestableClass {}
MyTestableClass.isTestable // true
@testable(false)
class MyClass {}
MyClass.isTestable // false
类成员装饰器
参数:
target:被修饰的类的原型对象 name:类成员的名字 descriptor:类成员的描述对象
function readonly(target, name, descriptor){
// descriptor对象原来的值如下
// {
// value: specifiedFunction,
// enumerable: false,
// configurable: true,
// writable: true
// };
descriptor.writable = false;
return descriptor;
}
class Person {
@readonly
name() { return `${this.first} ${this.last}` }
}
多个装饰器的执行顺序
洋葱模型,先从外到内进入,然后由内向外执行
function dec(id){
console.log(evaluated, id);
return (target, property, descriptor) => console.log(executed, id);
}
class Example {
@dec(1)
@dec(2)
method(){}
}
// evaluated 1
// evaluated 2
// executed 2
// executed 1
应用
延迟
class Page {
@delay(2000)
onClick(a) {
console.log("onClick");
}
}
function delay(time) {
return function (target, key, descriptor) {
const oldFunction = descriptor.value;
descriptor.value = function() {
setTimeout(() => {
oldFunction.apply(this, arguments);
}, time);
}
return descriptor;
}
}
节流
如果在定时器的时间范围内再次触发,则不予理睬,等当前定时器完成,才能启动下一个定时器任务。
class Page {
@throttle(2000)
onClick(a) {
console.log("onClick");
}
}
function throttle(time) {
return function (target, key, descriptor) {
const oldFunction = descriptor.value;
let isLock = false;
descriptor.value = function() {
if(isLock) { return; }
isLock = true;
oldFunction.apply(this, arguments);
setTimeout(() => {
isLock = false;
}, time);
}
return descriptor;
}
}
防抖
每次事件触发则删除原来的定时器,建立新的定时器。
class Page {
@debounce(2000)
onClick(a) {
console.log("onClick");
}
}
function debounce(time) {
return function (target, key, descriptor) {
const oldFunction = descriptor.value;
let timer = null;
descriptor.value = function () {
clearTimeout(timer);
timer = setTimeout(() => {
oldFunction.apply(this, arguments)
}, time);
};
return descriptor;
}
}
到此这篇关于详解如何在JavaScript中使用装饰器的文章就介绍到这了,更多相关JavaScript使用装饰器内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。
创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!