I believe that you must have encountered in the development of the second frame confirmation related requirements. It doesn't matter if you're using the secondary frame component of the UI framework, or if you're using your own wrapped frame component. You can't avoid the problem of lots of duplicate code in multiple uses. This accumulation of code makes the project unreadable. The project's code quality also became poor. So how do we solve the problem of double popbox code duplication? Use decorators.
What is a decorator?โ
Decorator is a new syntax in ES7. Decorators decorate classes, objects, methods, and properties. Add some other behavior to it. In layman's terms: wrapping a piece of code twice.
How to use decorators?โ
The purpose of decorators is to reuse code. Let's start with a small example
// declare a decorator
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;
};
// calc class
class Calculate {
// use log decorator
@log()
subtraction(a, b) {
return a - b;
}
}
const operate = new Calculate();
operate.subtraction(5, 2);
How about not using decorators?
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);
You'll see that the code is much more readable with decorators. Decorators don't care about the implementation of your internal code.
use Decorators in VUEโ
If your project is built using vue-cli and vue-cli is older than 2.5, you don't need to do any configuration to use it. If your project also includes Eslit then you need to enable syntax checking for decorator support in Eslit
// eslintrc.js
parserOptions: {
ecmaFeatures: {
// add decorator support
legacyDecorators: true;
}
}
Best practiceโ
Usually in a project we use a secondary box to delete:
// use element-ui
import { MessageBox, Message } from 'element-ui'
/**
* Confirm
* @param {String} title
* @param {String} content
* @param {String} confirmButtonText
* @param {Function} callback
* @returns
**/
export function confirm(title, content, confirmButtonText = 'Confirm') {
return function(target, name, descriptor) {
const originValue = descriptor.value
descriptor.value = function(...args) {
// custom confirm logic
MessageBox.confirm(content, title, {
dangerouslyUseHTMLString: true,
distinguishCancelAndClose: true,
confirmButtonText: confirmButtonText
}).then(originValue.bind(this, ...args)).catch(error => {
if (error === 'close' || error === 'cancel') {
Message.info('cancel operation'))
} else {
Message.info(error)
}
})
}
return descriptor
}
}
The confirm method performs a MessageBox component of element-UI that prompts the user to cancel when the user cancels.
now we can use the confirm decorator to add a confirm button to the method
import { confirm } from '@/util/decorator';
import axios form 'axios';
export default {
...
methods: {
// use confirm decorator
@confirm('Delete Record', 'Are you sure to delete this record?')
deleteRecord(id) {
// delete logic
axios.delete(`/api/record/${id}`)
}
}
}
Summaryโ
Decorators are used to rewrap a piece of code. Add some behavior actions and attributes to the code. Using decorators can greatly reduce code duplication. Improve code readability.