1、什么是装饰器
看个例子就懂了,正常开发是这样的:
1、先定义节流方法
methods: { throttle(func, delay) { var timer = null; return function() { var context = this; var args = arguments; if (!timer) { timer = setTimeout(function() { func.apply(context, args); timer = null; }, delay); } } } }
2、然后执行 A 方法
methods: { a() { this.throttle(() = >{ //执行业务逻辑 }, 400) } }
反正就是各种嵌套,看起来代码很脓肿,接下来看看【装饰器】怎么写。
//使用装饰器过后的写法 import { throttle} from "@/utils/decorator"; methods: { @throttle(400) // 装饰器(节流) a() { // 执行业务逻辑 //此时会发现点击效果跟上面写法一样 console.log('执行业务') }, }
现在看到的写法是不是凉快了很多,没有多层嵌套。
2、装饰器怎么封装
1、在工具文件创建 decorator.js
// utils/decorator.js /** * 节流,一定时间内,只能触发一次操作 * @export * @param {Function} fn - 运行函数 * @param {Number} wait - 延迟时间 * @returns */ export function throttle(wait = 2000) { //返回值:被传递给函数的对象。 return function(target, name, descriptor) { // @param target 类本身 // @param name 装饰的属性(方法)名称 // @param descriptor 属性(方法)的描述对象 const fn = descriptor.value let canRun = true descriptor.value = async function(...args) { //具体的装饰器业务在这里面编写 if (!canRun) return await fn.apply(this, args) // 执行业务下的方法 canRun = false setTimeout(() = >{ canRun = true }, wait) } } }
2、在业务板块里面声明使用。
methods: { @throttle(400) // 装饰器(节流) a() { // 执行业务逻辑 //此时会发现点击效果跟上面写法一样 console.log('执行业务') }, }
现在看到代码是不是就没有那么脓肿了,就一行指令。
3、装饰器能干啥
现实开发中经常遇到节流,防抖,日志,按钮权限等等一些业务执行之前的拦截操作。
以下是我平时使用的一些装饰器,希望对看到这里的你有帮助!
// utils/decorator.js import { Dialog } from 'vant'; /** * loading 开关装饰器 * @param {String} loading 当前页面控制开关的变量名字 * @param {Function} errorCb 请求异常的回调 返回 error 一般不用写 * 如果 errorCb 为 function 为你绑定 this 如果是箭头函数 则第二个参数为 this * @example * @loading('pageLoading',function(){that.demo = '123123'}) * async getTable(){ * this.table = this.$apis.demo() * } * @example * @loading('pageLoading',(error,that)=>{that.demo = '123123'}) * async getTable(){ * this.table = this.$apis.demo() * } */ export function loading (loading, errorCb = Function.prototype) { return function (target, name, descriptor) { const oldFn = descriptor.value; descriptor.value = async function (...args) { try { this[loading] = true; await oldFn.apply(this, args); } catch (error) { errorCb.call(this, error, this); } finally { this[loading] = false; } }; }; } /** * 日志注入 * @export * @param {Function} fn - 运行函数 * @param {data} 日志需要的参数 * @returns */ export function log(data) { return function(target, name, descriptor) { const fn = descriptor.value; descriptor.value = async function(...args) { await logApi(data) // 自己的日志接口 await fn.apply(this, args); } } } // utils/decorator.js /** * 节流,一定时间内,只能触发一次操作 * @export * @param {Function} fn - 运行函数 * @param {Number} wait - 延迟时间 * @returns */ export function throttle(wait= 2000) { return function(target, name, descriptor) { const fn = descriptor.value let canRun = true descriptor.value = async function(...args) { if (!canRun) return await fn.apply(this, args) canRun = false setTimeout(() => { canRun = true }, wait) } } } // utils/decorator.js /** * 防抖,连续操作时,只在最后一次触发 * @export * @param {Function} fun - 运行函数 * @param {Number} wait - 延迟时间 * @returns */ export function debounce(wait= 2000) { return function(target, name, descriptor) { const fn = descriptor.value let timer = null descriptor.value = function(...args) { const _this = this._isVue ? this : target clearTimeout(timer) timer = setTimeout(() => { fn.apply(_this, args) }, wait) } } } /** * 表单校验 * @param {String} formElKey - 表单 el */ export const formValidation = (formElKey = 'formEl') => { return (target, name, descriptor) => { const method = descriptor.value descriptor.value = async function() { const _this = this._isVue ? this : target const isValidate = _this[formElKey]?.validate if (isValidate) { const [, res] = await to(isValidate()) if (!res) return false } return method.apply(_this, arguments) } } } // utils/decorator.js /** * 确认框 * @param {String} title - 标题 * @param {String} concent - 内容 * @param {String} confirmButtonText - 确认按钮名称 * @returns */ export const alertDecorator = ({title = '提示', message = '请输入弹窗内容', confirmButtonText = '我知道了'}) => { return (target, name, descriptor) => { const fn = descriptor.value; descriptor.value = function (...args) { Dialog.alert({title, message, confirmButtonText}).then(() => { fn.apply(this, args); }); } } } /** * 缓存计算结果 * @export * @param {Function} fn * @returns */ export function cached() { return function(target, name, descriptor) { const method = descriptor.value const cache = new Map() descriptor.value = function() { const _this = this._isVue ? this : target const key = JSON.stringify(arguments) if (!cache.has(key)) { cache.set(key, method.apply(_this, arguments)) } return cache.get(key) } } }
以上就是为大家分享的前端装饰器的使用,先收藏一下,如果大家实战划水时间提高了,别忘了回来点个赞哦!如果大家觉得有用,就分享给你的小伙伴吧!剩下的就是快乐的划水了,哈哈。