The following three decorators are all implemented using async/await to transform async into synchronization.

Methods that require to be decorated must be written async/await, which is very convenient to use and the implementation is completely hidden inside the decorator.

The first two are used in vUE for class notation in ts environment. However, once you look at the logic, you can easily modify it to work with VUE components in your JS environment.

1. Add a variable to vue indicating that initialization is complete.

It indicates that the initialization logic related to the service is complete. For example, in the search function, loading is displayed. If the result is empty, no data is displayed temporarily. But the first time you open the page, the search is not complete, but there is no data for the time being and it is not appropriate to use a variable like this to handle the boundary case for the VUE in the TS environment

Add this property through a decorator and wrap vue’s Created, Mounted, and beforeDestroy methods. When a created or Mounted request completes, set pageIsReady to True. When using this decorator, there is no sense in the business code, no mental burden whatsoever.

import { Constructor } from"vue/types/options"; export type WrapReadyProperty<T> = T & { pageIsReady? : Boolean} /** * When created and Mounted are both created and created, the component will be injected with the property pageIsReady. Mounted or created is async/await. (Depending on which method the request is made to initialize the component) * It can then be used directly in the template. * Use the isPageReady. Call (this) method in script; */ exportdefaultfunction PageReadyStatus() { let createdDone = false; let mountedDone = false; function isCreatedMountedAllDone() { return createdDone && mountedDone; } returnfunction pageReadyEnhancement<T extends Constructor>(target: T) { const oldMounted = target.prototype.mounted || function() { } const oldCreated = target.prototype.created || function() { } const oldBeforeDestroy = target.prototype.beforeDestroy || function() { } target.prototype.pageIsReady = false; target.prototype.created = asyncfunction(... params: any[]) { await oldCreated.apply(this, params); createdDone = true; this.pageIsReady = isCreatedMountedAllDone() } target.prototype.mounted = asyncfunction(... params: any[]) { await oldMounted.apply(this, params); mountedDone = true; this.pageIsReady = isCreatedMountedAllDone() } target.prototype.beforeDestroy = asyncfunction(... params: any[]) { await oldBeforeDestroy.apply(this, params); mountedDone = false; createdDone = false; this.pageIsReady = false; } return target }; } exportfunction isPageReady(this: WrapReadyProperty<Vue>) { returnthis.pageIsReady }Copy the code

2. Add anti-shock and loading styles to event callback functions and button Dom

Vue in TS environment

The process of being decorated by wrapping a decorator. The request is wrapped async/await. This way you only need to use an await inside the decorator to know if the wrapped method has finished executing. At the same time, you can take the clicked DOM element from the event object and modify it.

*/ exportDefaultFunction buttonThrottle() {let pending = false; returnfunction(target: any, name: string): any { const btnClickFunc = target[name]; const newFunc = asyncfunction(this: Vue, ... params: any[]) { if (pending) { return; } const event:Event = params[params.length - 1]; let btn = event.target as HTMLElement pending = true; const recoverCursor = changeCursor(btn); try { await btnClickFunc.apply(this, params); } catch (error) { console.error(error); } recoverCursor(); pending = false; }; target[name] = newFunc; return target; }; } function changeCursor(btn? : HTMLElement) { if (btn == null) { return() => {}; } const oldCursor = btn.style.cursor; btn.style.cursor = "wait"; return() => { btn.style.cursor = oldCursor; }; }Copy the code

Usage: Use this decorator on the click event function. The decorator automatically detects that the function is complete and adds the Point: Wait attribute to the BUTTON’s Dom node during execution

import { Component, Vue } from"vue-property-decorator";
    import buttonThrottle from"@/ui/view/utils/buttonThrottle";

    type Member = { account_no: string; name: string; warn?: string };
    @Component({ components: {} })
    exportdefaultclass AddMemberInput extends Vue {        @buttonThrottle()
        private async confirmAdd() {
            awaitthis.addMembers(this.getVaildMembers());
        }
    }
Copy the code

3. Mounted Displays a white screen

Objects that wrap vUE in THE VUE for JS

/ / get mounted or created with async/await, then get the root of the component with this pointing to vue power, and modify it as needed. The following code just hides the component. In fact, you can write more complex logic and display something else during loading. Do what you want.

function firstPaintControl(vueObj) { let oldMounted = vueObj.mounted || function() {}; vueObj.mounted = asyncfunction(... params) { this.$el.style.visibility = 'hidden'; await oldMounted.apply(this, params); this.$el.style.visibility = 'visible'; }; return vueObj; }Copy the code