温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Vue中怎么使用装饰器

发布时间:2022-01-25 15:07:23 来源:亿速云 阅读:261 作者:iii 栏目:开发技术

本篇内容介绍了“Vue中怎么使用装饰器”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

    什么是装饰器?

    Decorator是ES7的一个新语法。Decorator通过对类、对象、方法、属性进行修饰。对其添加一些其他的行为。通俗来说:就是对一段代码进行二次包装。

    装饰器的使用

    使用方法很简单 我们定义一个函数

    const  decorator =  (target, name, descriptor) => {
     var oldValue = descriptor.value;
     descriptor.value = function(){
        alert('哈哈')
        return oldValue.apply(this,agruments)
           }
      return descriptor
    }
    // 然后直接@decorator到函数、类或者对象上即可。

    装饰器的目的旨在对代码进行复用。下面我们先来一个小例子看看

    js中使用装饰器

    //定义一个装饰器 
    const log = (target, name, descriptor) => {
      var oldValue = descriptor.value;
      descriptor.value = function() {
        console.log(`Calling ${name} with`, arguments);
        return oldValue.apply(this, arguments);
      };
      return descriptor;
    }
       //计算类
      class Calculate {  
     
      //使用装饰器
      @log() 
      function  subtraction(a,b){
         return  a - b
       }
     }
     
     const operate  = new Calculate()
      operate.subtraction(5,2)

    不使用装饰器

    const log = (func) => {
      if(typeof(func) !== 'function') {
        throw new Error(`the param must be a function`);
      }
      return (...arguments) => {
        console.info(`${func.name} invoke with ${arguments.join(',')}`);
        func(...arguments);
      }
    }
    
    const subtraction = (a, b) => a + b;
    
    const subtractionLog = log(subtraction);
    
    subtractionLog(10,3);

    这样一对比你会发现使用装饰器后代码的可读性变强了。装饰器并不关心你内部代码的实现。

    vue 中使用装饰器

    如果你的项目是用vue-cli搭建的 并且vue-cli的版本大于2.5 那么你无需进行任何配置即可使用。如果你的项目还包含eslit 那么你需要在eslit中开启支持装饰器相关的语法检测

    //在 eslintignore中添加或者修改如下代码:
    parserOptions: {
        ecmaFeatures:{
          // 支持装饰器
          legacyDecorators: true
        }
      }

    加上这段代码之后eslit就支持装饰器语法了。

    通常在项目中我们经常会使用二次弹框进行删除操作:

    //decorator.js
    //假设项目中已经安装了 element-ui
    import { MessageBox, Message } from 'element-ui'
    /**
     * 确认框
     * @param {String} title - 标题
     * @param {String} content - 内容
     * @param {String} confirmButtonText - 确认按钮名称
     * @param {Function} callback - 确认按钮名称
     * @returns
       **/
    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
      }
    }

    如上代码 confirm方法里执行了一个element-ui中的MessageBox组件 当用户取消时 Message组件会提示用户取消了操作。

    我们在test()方法上用装饰器修饰一下

    import { confirm } from '@/util/decorator'
    import axios form 'axios'
    export default {
    name:'test',
    data(){
    return {
      delList: '/merchant/storeList/commitStore'
        }
      }
    },
    methods:{
     @confirm('删除门店','请确认是否删除门店?')
      test(id){
       const {res,data} = axios.post(this.delList,{id})
       if(res.rspCd + '' === '00000') this.$message.info('操作成功!')
      }
    }

    此时用户点击某个门店进行删除。装饰器将会起作用。弹出如下图所示:

    Vue中怎么使用装饰器

    当我点击取消时:

    Vue中怎么使用装饰器

    tips: 用户取消了操作.被修饰的test方法不会执行

    当我们点击确定时:

    Vue中怎么使用装饰器

    接口被调用了 并且弹出了message

    一些常用的装饰器

    下面小编罗列了几个小编在项目中常用的几个装饰器,方便大家使用

    1. 函数节流与防抖

    函数节流与防抖应用场景是比较广的,一般使用时候会通过throttle或debounce方法对要调用的函数进行包装,现在就可以使用上文说的内容将这两个函数封装成装饰器, 防抖节流使用的是lodash提供的方法,大家也可以自行实现节流防抖函数哦

    import { throttle, debounce } from 'lodash'
    /**
     * 函数节流装饰器
     * @param {number} wait 节流的毫秒
     * @param {Object} options 节流选项对象
     * [options.leading=true] (boolean): 指定调用在节流开始前。
     * [options.trailing=true] (boolean): 指定调用在节流结束后。
     */
    export const throttle =  function(wait, options = {}) {
      return function(target, name, descriptor) {
        descriptor.value = throttle(descriptor.value, wait, options)
      }
    }
    
    /**
     * 函数防抖装饰器
     * @param {number} wait 需要延迟的毫秒数。
     * @param {Object} options 选项对象
     * [options.leading=false] (boolean): 指定在延迟开始前调用。
     * [options.maxWait] (number): 设置 func 允许被延迟的最大值。
     * [options.trailing=true] (boolean): 指定在延迟结束后调用。
     */
    export const debounce = function(wait, options = {}) {
      return function(target, name, descriptor) {
        descriptor.value = debounce(descriptor.value, wait, options)
      }
    }

    封装完之后,在组件中使用

    import {debounce} from '@/decorator'
    
    export default {
      methods:{
        @debounce(100)
        resize(){}
      }
    }

    2. loading

    在加载数据的时候,为了个用户一个友好的提示,同时防止用户继续操作,一般会在请求前显示一个loading,然后在请求结束之后关掉loading,一般写法如下

    export default {
      methods:{
        async getData() {
          const loading = Toast.loading()
          try{
            const data = await loadData()
            // 其他操作
          }catch(error){
            // 异常处理
            Toast.fail('加载失败');
          }finally{
            loading.clear()
          }  
        }
      }
    }

    我们可以把上面的loading的逻辑使用装饰器重新封装,如下代码

    import { Toast } from 'vant'
    
    /**
     * loading 装饰器
     * @param {*} message 提示信息
     * @param {function} errorFn 异常处理逻辑
     */
    export const loading =  function(message = '加载中...', errorFn = function() {}) {
      return function(target, name, descriptor) {
        const fn = descriptor.value
        descriptor.value = async function(...rest) {
          const loading = Toast.loading({
            message: message,
            forbidClick: true
          })
          try {
            return await fn.call(this, ...rest)
          } catch (error) {
            // 在调用失败,且用户自定义失败的回调函数时,则执行
            errorFn && errorFn.call(this, error, ...rest)
            console.error(error)
          } finally {
            loading.clear()
          }
        }
      }
    }

    然后改造上面的组件代码

    export default {
      methods:{
        @loading('加载中')
        async getData() {
          try{
            const data = await loadData()
            // 其他操作
          }catch(error){
            // 异常处理
            Toast.fail('加载失败');
          }  
        }
      }
    }

    3. 确认框

    当你点击删除按钮的时候,一般都需要弹出一个提示框让用户确认是否删除,这时候常规写法可能是这样的

    import { Dialog } from 'vant'
    
    export default {
      methods: {
        deleteData() {
          Dialog.confirm({
            title: '提示',
            message: '确定要删除数据,此操作不可回退。'
          }).then(() => {
            console.log('在这里做删除操作')
          })
        }
      }
    }

    我们可以把上面确认的过程提出来做成装饰器,如下代码

    import { Dialog } from 'vant'
    
    /**
     * 确认提示框装饰器
     * @param {*} message 提示信息
     * @param {*} title 标题
     * @param {*} cancelFn 取消回调函数
     */
    export function confirm(
      message = '确定要删除数据,此操作不可回退。',
      title = '提示',
      cancelFn = function() {}
    ) {
      return function(target, name, descriptor) {
        const originFn = descriptor.value
        descriptor.value = async function(...rest) {
          try {
            await Dialog.confirm({
              message,
              title: title
            })
            originFn.apply(this, rest)
          } catch (error) {
            cancelFn && cancelFn(error)
          }
        }
      }
    }

    然后再使用确认框的时候,就可以这样使用了

    export default {
      methods: {
        // 可以不传参,使用默认参数
        @confirm()
        deleteData() {
          console.log('在这里做删除操作')
        }
      }
    }

    “Vue中怎么使用装饰器”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注亿速云网站,小编将为大家输出更多高质量的实用文章!

    向AI问一下细节

    免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

    vue
    AI