Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”.

The Decorator syntax has not been proposed, so it is rarely used in projects. But recently there was a need.

What is a decorator

A decorator is a function named @ +. It can precede the definition of classes and class methods.

I understand that a decorator is a function generator, a higher-order function.

Decorators can be used to decorate classes and methods. Decorators can be nested and can be passed in parameters. For the syntax, see ECMAScript 6 Primer – Decorators.

The specific requirements

When writing service requirements, many operations need to be confirmed twice. For example, a confirmation window needs to be added before deleting a file.

Since we’re using Vue2. X + Element UI, the code looks something like this:

deleteFile(data) {
    this.$confirm('This operation will permanently delete the file. Do you want to continue? '.'tip', {
        type: 'warning'
    }).then(() = > {
        // Delete a file
    }).catch(() = > {});
}
Copy the code

Double-validation is required for many dangerous operations, so adding the validation part to each function felt a bit redundant, so I thought of using the annotator to remove the confirm part. The code is as follows:

import { MessageBox } from 'element-ui';

function confirmation(target, name, descriptor) {
    let oldValue = descriptor.value;
    descriptor.value = function(. args) {
        MessageBox.confirm('This operation will permanently delete the file. Do you want to continue? '.'tip')
            .then(oldValue.bind(this. args)) .catch(() = > {});
    };

    return descriptor;
}
Copy the code

This can be done by adding @confirmation to the function that requires a second confirmation:

@confirmation
deleteFile(data) {
    // Delete a file
}
Copy the code

Different operations require different hints, so add a parameter to the annotator.

import { MessageBox } from 'element-ui';

export function confirmation(message) {
    return function(target, name, descriptor) {
        let oldValue = descriptor.value;
        descriptor.value = function(. args) {
            MessageBox.confirm(message, 'tip')
                .then(oldValue.bind(this. args)) .catch(() = > {});
        };

        returndescriptor; }}Copy the code

Use the code

@confirmation('This operation will permanently delete the file. Do you want to continue? ')
deleteFile(data) {
    // Delete a file
}
Copy the code

The related configuration

My project was created via the Vue Cli and required to add ESlint configuration.

"parserOptions": {
    // ...
    "ecmaFeatures": {
        "legacyDecorators": true}}Copy the code