前言

1、vue@2.6.14

2、使用@装饰器需安装@babel/plugin-proposal-decorators 依赖

"@babel/plugin-proposal-decorators": "^7.18.10"

3、配置.babelrc

{
"plugins": [
  [
  "@babel/plugin-proposal-decorators",
  {
  	"legacy": true
  }
  ]
]
}

实现

下载文件封装装饰exportFile.js

import { Message } from 'element-ui';
import Http from 'axios';
/**
 * 文件下载
 * @param {String} requestMethods - 请求方式 GET/POST
 * @param {String} url - 接口地址
 * @param {String} query - 接口参数
 * @param {String} filename - 导出文件名称
 * @returns
   **/
const encodeParams = (params) => {
    const r = '?',
        p = [];
    for (const key in params) {
        p.push(`${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`);
    }
    return r + p.join('&');
};
export function exportFile(
    requestMethods,
    url,
    query,
    filename
) {
    return function(descriptor) {
        descriptor.value = function() {
            if (typeof query === "undefined") {
                query = {};
            }
            if (requestMethods === 'GET' && query) {
                url += encodeParams(query);
            }
            return Http({
                method: requestMethods,
                url: url,
                responseType: 'blob',
                data: query
            }).then(res => {
                if (res.type === 'application/json') {
                    Message.error('下载失败');
                } else {
                    let blob = new Blob([res], {type: "application/octet-stream"});
                    let _filename = filename ? filename +'.xls' : '导出件.xls';
                    if ('download' in document.createElement('a')) {
                        let url = window.URL.createObjectURL(blob);
                        let link = document.createElement('a');
                        link.style.display = "none";
                        link.href = url;
                        link.setAttribute('download', _filename);
                        document.body.appendChild(link);
                        link.click();
                        document.body.removeChild(link);
                        window.URL.revokeObjectURL(url);
                    } else {
                        window.navigator.msSaveBlob(blob, _filename);
                    }
                }
            });

        }
        return descriptor
    }
}

// 使用
import { exportFile } from './exportFile.js'
@exportFile('GET', 'http://127.0.0.1:8000/exportToExcel', {id: 'file123'}, '导出文件名称')
functionName(functionParams) {} 

询问框装饰confirm.js

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) {
    console.log('descriptor==',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
  }
}

// 使用
import { confirm } from './confirm.js'
@confirm('删除','请确认是否删除选择数据?')
functionName(functionParams) {} 

加载装饰loading.js

import { Loading } from 'element-ui';
 
/**
 * loading 装饰器
 * @param message 提示信息
 * @param closeTime 定时关闭的时长
 */
export const loading =  function(message = '加载中...', closeTime = 2000) {
  return function(descriptor) {
    descriptor.value = async function() {
      const loading = Loading.service({
        lock: true,
        text: message,
        spinner: 'el-icon-loading',
        background: 'rgba(0, 0, 0, 0.7)'
      });
      setTimeout(() => {
        loading.close();
      }, closeTime);
    }
      return descriptor
  }
}

// 使用
import { loading } from './loading.js'
@loading('页面加载中…')
functionName(functionParams) {}

防抖装饰debounce.js

import { debounce } from 'lodash'

 
/**
 * 函数防抖装饰器
 * @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 './debounce.js'
@debounce(1000)
functionName(functionParams) {}

节流装饰throttle.js

import { throttle } 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)
  }
}

// 使用
import { throttle } from './throttle.js'
@throttle(1000)
functionName(functionParams) {}

PS:Leading decorators must be attached to a class declaration. 装饰器作用于类或函数。

其他

vscode +vue 使用装饰器代码提示Property assignment expected.Vetur(1136)

在vscode中的setting.json中配置"vetur.validation.script": false 去除vetur对script的校验。

vscode +vue 使用装饰器代码提示';' expected.Vetur(1005)

在vscode中的setting.json中配置"vetur.experimental.templateInterpolationService": false

参考文档:https://www.jb51.net/article/235827.htm

posted on 2022-08-24 10:35  羽丫头不乖  阅读(203)  评论(0编辑  收藏  举报