Today I attended an interview, which impressed me deeply. After the interview, I made a summary to share with you. If it helps you, give it a thumbs up.

Apply for a senior Vue engineer position, a very strange position, think about their own Vue for more than three years, should be a senior bar, treatment in the city is good, more than ten K, 15 salary.

The interviewer was a seven-year veteran. The interview was full of questions about Vue and Webpack, which is a real need for a senior Vue engineer.

After an hour and a half of torture in terms of Vue API, principle and Webpack configuration, I thought it should be over, but unexpectedly the interviewer pointed to my backpack and said, “Do you have a computer?” I unconsciously answered yes. “Then you write a simple component on the spot, the charger with it?” I swear I won’t bring a laptop in my backpack next time. For money, he had to take out his computer and asked, “What are your needs?”

“Simple implementation of a loading animation of the component, animation effects with CSS3 development, components show hidden to have excessive effects, you can use this.$loading(options) call, can also use v-loading call. One hour, is that enough?”

“Using this, using V-loading, I was nervous and didn’t have any ideas at first.”

I’ve never written this component before, but I remember that element-UI is called this way. Either go to the project and read the source Code for element-UI, or forget it, the big guy is sitting behind me. We have to settle down step by step.

One, the implementation of loading animation and display hidden transition effect

CSS3 animation property is used to load the animation, and the transition effect is realized by the Vue built-in component Transition.

The first is the page layout, which is simple and quick to write

//loading.vue <template> <transition name="loading"> <div v-show="isShow" class="ui-loading-wrap"> <div class="ui-loading-mask"></div> <div class="ui-loading"> <div class="ui-loading-icon"></div> <div class="ui-loading-text">{{ text }}</div> </div> </div> </transition> </template> <script> export default { props:{ Text :{type:String, default:' loading '}, isShow:{type: Boolean, default: false}}} </script>Copy the code

And let’s do that. Shows hidden transition effects. The name of the transition built-in component is v by default. It is used to automatically generate CSS transition class names, such as

  • v-enter: Defines the state at the beginning of the transition. It takes effect before the element is inserted and is removed the next frame after the element is inserted. `
  • v-leave-to: Defines the end state of the exit transition. Remove after the transition/animation is complete.
  • v-enter-active: Defines the state when the transition takes effect.
  • v-leave-active: Defines the state when the exit transition takes effect.

If name is set to loading, loading-enter, loading-leave-to, loading-enter-active and loading-leave-active will be generated. These classnames can be used to make excessive effects. The following code

// load.vue. loading-enter-active {transition: all 0.3s ease; }. Loading-leave-active {transition: all 0.3s ease; } .loading-enter, .loading-leave-to { opacity: 0; }Copy the code

Then write the page layout style, using flex layout to center the loading animation.

//loading.vue ui-loading-wrap{ position: absolute; z-index: 999; top: 0px; bottom: 0; left: 0; right: 0; } .ui-loading-mask { height: 100%; background-color: #000; Opacity: 0.2; } .ui-loading { position: absolute; z-index: 1001; top: 0px; bottom: 0; left: 0; right: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; .ui-loading-text { color: #ffffff; }}Copy the code

First draw a circle using the border and border-radiusCSS properties, and then set the border color in the order of top, right, bottom and left. Use animation and @keyframes to rotate the circle to complete the loading animation.

//loading.vue .ui-loading-icon{ width: 40px; height: 40px; margin-bottom: 20px; border-radius: 50%; border-top:3px solid #c7f7e8; border-right:3px solid #c6ffed; border-bottom:3px solid #b4f8e3; border-left:3px solid #a0fadd; animation:turn 1s linear infinite; } @keyframes turn{ 0%{-webkit-transform:rotate(0deg); } 25%{-webkit-transform:rotate(90deg); } 50%{-webkit-transform:rotate(180deg); } 75%{-webkit-transform:rotate(270deg); } 100%{-webkit-transform:rotate(360deg); }}Copy the code

I looked back at the interviewer, who nodded deadpan and said to continue. $loading(options) this.$loading(options)

This.$loading(options

This represents Vue, so $loading should be mounted on vue. prototype. I thought about it for 10 minutes. I had no idea. When I am about to give up, I suddenly realize that the DOM element generated by the loading component is inserted into the root node of the page, so I just need to get the DOM element generated by the loading component in the $loading method and insert it into the corresponding element.

Remember that Vue has an instance attribute, vm.$el, which can fetch DOM elements. You can’t add a new Vue to the $loading method.

To create a subclass, remember that there is a global API for Vue. Extend that seems to extend from the Vue class to create a subclass. Is to generate a child constructor based on the Vue constructor that has all the methods of the Vue constructor.

To be honest, the vue. extend API is rarely used at work, except that its argument is an object. If you want to use vue.extend to create a constructor Loading, then you can get an instance Loading in new Loading(), and then you can get the DOM element generated by Loading.$el. The vue. extend argument should be the export default object of the loading component.

The loading component should be modified before writing. To enable the loading component to display its instance loading, you can use load. isShow = true instead of using the props passer to set isShow to true.

//loading.vue
<script>
export default {
    data:{
        text:{
            type:String,
            default:'加载中'
        },
        isShow:{
            type: Boolean,
            default: false
        }
    }
}
</script>
Copy the code

Create a new load.js file.

UiLoading is the export default object of the loading component, which creates the constructor loading with vue.extend (UiLoading).

Loading.$el(DOM generated by Loading component) is inserted into the body. Using vue. nextTick to set load. isShow to true after page rendering is complete, the loaded animation component will be displayed.

Prototype.$loading = LoadingInit, so this.$loading(options) is called.

To disable the loading component, remove the DOM generated by the loading component from its parent element (this.$el.parentNode), and then call this.$destroy() to destroy the loading component.

The specific code is as follows.

//loading.js
import Vue from 'vue';
import UiLoading from './loading.vue';

const Loading = Vue.extend(UiLoading);
let loading = undefined;

Loading.prototype.close = function () {
    if (loading) {
        loading = undefined
    }
    this.isShow = false;
    setTimeout(() => {
        if (this.$el && this.$el.parentNode) {
            this.$el.parentNode.removeChild(this.$el);
        }
        this.$destroy();
    }, 300)
}

const LoadingInit = (options = {}) => {
    if (loading) {
        loading.close();
    }
    let parent;
    if(options.parent && Object.prototype.toString.call(options.parent) == '[object String]'){
        parent = document.querySelector(options.parent);
    }else{
        parent =  document.body
    }
    loading = new Loading({
        el: document.createElement('div'),
        data: options
    })
    parent.appendChild(loading.$el);
    Vue.nextTick(() => {
        loading.isShow = true;
    })
    return loading;
}
Vue.prototype.$loading = LoadingInit;
export default LoadingInit
Copy the code

After writing, import loading. Js in main.js. Try calling the loading animation component to show normally hidden. Let’s look at the time has passed more than 40 minutes, there is no time to see what the interviewer’s expression, hurry up to implement v-loading call.

Iii. Implement v-loading call

How to use this.$loading(options) to call the loading component is very easy to use v-loading. Create a new v_load.js file.

Extend (UiLoading) to create the constructor Loading as usual.

In the bind hook function, the first parameter el is the element bound by the v-loading instruction, which can be used to manipulate the DOM directly. The second parameter binding can obtain the value of the instruction binding.

$el(DOM generated by Loading component) is inserted into EL, and instance Loading is mounted to el. Loading as a cache. Use vue. nextTick to assign binding. Value to el.loading. IsShow in the loading component after page rendering is complete.

In the update hook function, when the binding value of the instruction changes, the binding. Value is assigned to el.loading. IsShow, so that the loading component can be shown and hidden.

Finally, in the unbind hook function, the DOM generated by the loading component is removed from el.loading.$el.parentNode when the instruction is unbound. $destroy() is called to destroy the loading component and null is set to el.loading to remove memory usage.

The specific implementation code is as follows.

import Vue from 'vue'
import UiLoading from './loading.vue'
const Loading = Vue.extend(UiLoading)

Vue.directive('loading', {
    bind(el, binding) {
        const loading = new Loading({
            el: document.createElement('div'),
            data: {}
        })
        el.appendChild(loading.$el);
        el.loading = loading;
        Vue.nextTick(() => {
            loading.isShow = binding.value;
        })
    },
    update(el, binding) {
        if (binding.oldValue !== binding.value) {
            el.loading.isShow = binding.value;
        }
    },
    unbind(el) {
        const element = el.loading.$el;
        if (element.parentNode) {
            element.parentNode.removeChild(element);
        }
        el.loading.$destroy();
        el.loading = null;
    }
})
Copy the code

After writing, import v_load.js in main.js. Try calling the loading animation component to show normally hidden.

Four, afterword.

When you’re done, look at the time. 56 minutes. That’s four minutes less than an hour. The interviewer takes a look at the page and says, “I’ll wrap up the code and send it to me. I’ll talk to you later.”

After chatting with hr about the topic of welfare benefits, HR finally said: “I will give you a reply within five working days”. The interview is over.

Go home and reflect on the interview process. In terms of Vue API, principle and Webpack configuration, I did not have too much delay. It was very smooth, but I was stuck for more than ten minutes in the process of writing loading components, which made the interviewer feel a little unskilled.

Vue. Extend this API in the usual work is really rarely used, but finally there is an implementation, I hope to have a good result, a bit of worry and loss.

At 21:54 on August 17, 2020.