前言
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