decorator装饰器通过对类、对象、方法、属性进行修饰,对其添加一些其他行为,即对一段代码进行二次包装。 装饰器只能用于类和类的方法,不能用于函数,因为存在函数提升。
一、使用方法: 1 2 3 4 5 6 7 const decorator = (target,name,descriptor ) => { var oldValue = descriptor.value descriptor.value = function ( ) { return oldValue.apply(this ,arguments ) } return descriptor }
使用装饰器可以不需要关注代码内部的实现,增强了代码的可读性。
vue中使用装饰器:
项目中使用eslint,需要开启装饰器相关语法的检测。
1 2 3 4 5 6 7 parserOptions: { parser: 'babel-eslint' , ecmaFeatures:{ legacyDecorators: true } },
二、Vue项目使用Element-Ui组件库进行二次弹窗确认相关操作: 1、工具函数decorator.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 import { MessageBox, Message } from 'element-ui' export function confirm (title, content, confirmButtonText = '确定' ) { return function (target, name, descriptor ) { const originValue = descriptor.value descriptor.value = function (...args ) { MessageBox.confirm(content, title, { dangerouslyUseHTMLString: true , distinguishCancelAndClose: true , confirmButtonText: confirmButtonText }).then(originValue.bind(this , ...args)).catch(error => { if (error === 'close' || error === 'cancel' ) { Message.info('用户取消操作' ) } else { Message.info(error) } }) } return descriptor } }
2、页面引入装饰器函数
1 2 3 4 5 6 7 <template > <div class ="about" > <h1 > This is an about page</h1 > <p > 装饰器</p > <button @click ='test' > confirm</button > <button > cancel</button > </div > </template >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 import { confirm } from './decorator.js' export default { name: 'about' , methods: { @confirm('删除' , '确认删除?' ) test () { this .$message.success('success!!' ) } } }
三、前端API请求缓存 前端 API 请求缓存是前端性能优化的一个方案。
1、key值错误提示 1 const generateKeyError = new Error ('Can not generate key from name and argument' )
2、生成key值 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 function generateKey (name,argument ) { const params = Array .from(argument).join(',' ) try { return `${name} :${params} ` }catch { return generateKeyError } }function decorate (handleDescription,entryArgs ) { if (isDescriptor(entryArgs[entryArgs.length - 1 ])){ return handleDescription(...entryArgs,[]) }else { return function ( ) { return handleDescription(...Array.prototype.slice.call(arguments ),entryArgs) } } }function handleApiCache (target, name, descriptor, ...config ) { const fn = descriptor.value descriptor.value = function ( ) { const key = generateKey(name, arguments ) if (key === generateKeyError) { return fn.apply(null , arguments ) } let promise = ExpriesCache.get(key) if (!promise) { promise = fn.apply(null , arguments ).catch(error => { ExpriesCache.delete(key) return Promise .reject(error) }) ExpriesCache.set(key, promise, config[0 ]) } return promise } return descriptor; }function ApiCache (...args ) { return decorate(handleApiCache, args) }
3、api接口处使用ApiCache() 1 2 3 4 5 6 7 class Api { @ApiCache(10 ) getData(params1,params2){ return request.get('/getList' ) } }