1. Tell me about your understanding of SPA single page. What are its advantages and disadvantages?

SPA (Single-Page Application) loads the appropriate HTML, JavaScript, and CSS only when the Web page is initialized. Once the page is loaded, SPA will not reload or jump to the page because of user operations; Instead, a routing mechanism is used to transform HTML content, UI interaction with the user, and avoid page reloading.

Advantages:

  • User experience is good, fast, content changes do not need to reload the entire page, avoid unnecessary jump and repeat rendering;
  • Based on the above point, SPA is relatively less pressure on the server;
  • The responsibilities of the front and back end are separated, the architecture is clear, the front end carries out interactive logic, and the back end is responsible for data processing;

Disadvantages:

  • The initial loading is time-consuming: In order to realize the functions and display effect of a single-page Web application, JavaScript and CSS need to be loaded uniformly during the page loading, and some pages need to be loaded on demand.
  • Forward and backward routing management: Since the single-page application displays all the content in one page, the forward and backward function of the browser cannot be used, and all page switching needs to establish stack management.
  • SEO is difficult: because all content is dynamically replaced on one page, it has a natural weakness in SEO.

2. What’s the difference between V-show and V-IF?

V-if is true conditional rendering because it ensures that event listeners and child components within the conditional block are properly destroyed and rebuilt during the toggle; It is also lazy: if the condition is false at the initial render, nothing is done — the condition block is rendered until it becomes true for the first time.

V-show is much simpler — the element is always rendered regardless of the initial condition, and simply switches based on the “display” property of the CSS.

Therefore, V-if is suitable for scenarios where conditions are rarely changed at runtime and do not need to be switched frequently; V-show is suitable for scenarios that require very frequent switching conditions.

How to dynamically bind Class and Style?

Classes can be dynamically bound using object and array syntax:

  • Object syntax:

    <div v-bind:class="{ active: isActive, 'text-danger': hasError }"></div>
    
    data: {
      isActive: true,
      hasError: false
    }
    Copy the code
  • Array syntax:

    
    data: {
      activeClass: 'active',
      errorClass: 'text-danger'
    }
    Copy the code

Style can also be dynamically bound through object and array syntax:

  • Object syntax:

    <div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
    
    data: {
      activeColor: 'red',
      fontSize: 30
    }
    Copy the code
  • Array syntax:

    <div v-bind:style="[styleColor, styleSize]"></div>
    
    data: {
      styleColor: {
         color: 'red'
       },
      styleSize:{
         fontSize:'23px'
      }
    }
    Copy the code

4. How to understand the one-way data flow of Vue?

All prop causes a one-way downward binding between parent and child: updates to the parent prop flow down to the child component, but not vice versa. This will prevent the state of the parent component from changing unexpectedly from the child component, which can cause your application’s data flow to be difficult to understand.

Additionally, every time the parent component is updated, all prop in the child component will be refreshed to the latest value. This means that you should not change a prop inside a child component. If you do, Vue will issue an alert in the browser’s console. When the child component wants to modify, it can only send a custom event through $Emit. After receiving the event, the parent component will modify it.

There are two common situations in which you try to change a prop:

  • This prop is used to pass an initial value; The child component next wants to use it as a local prop data. In this case, it is best to define a local data property and use the prop as its initial value:

    props: ['initialCounter'],
    data: function () {
      return {
        counter: this.initialCounter
      }
    }
    Copy the code
  • The prop is passed in with a raw value and needs to be converted. In this case, it is best to use the value of the prop to define a computed property

    props: ['size'],
    computed: {
      normalizedSize: function () {
        return this.size.trim().toLowerCase()
      }
    }
    Copy the code

5. What are the differences between Computed and Watch and what are the application scenarios?

Computed: The value of computed is cached. Only when the value of the dependent attribute changes, the value of computed is recalculated the next time the value of computed is obtained.

Watch: More of a “watch” function, similar to the listening callback of some data, every time the listening data changes, the callback will be executed for subsequent operations;

Application scenario:

  • Use Computed when you need to perform numeric computations that depend on other data because the caching feature of computed avoids having to recalculate the value every time it is fetched.

  • Watch should be used when we need to perform an asynchronous or expensive operation when data changes. Using the Watch option allows us to perform an asynchronous operation (access an API), limits how often we perform the operation, and sets the intermediate state until we get the final result. These are things that computational properties can’t do.

5.1 Getters and Setters for computed

Talk about getters and setters for computed.

Problem description

A lot of times, when I ask this question, the answer will be vue getters and setters, subscriber mode, something like that, and I’ll just say that’s not what I’m asking, that’s computed, and I’ll just say that’s computed, A lot of times the answer is computed, the default, and you just use the getter, and then you go on to ask what to do if you want to set the value back, and of course you don’t get the answer to that point.

Hope the answer

` ` ` <! Computed: {fullName: {// getter get:} // computed: {fullName: {// getter get:} function () { return this.firstName + ' ' + this.lastName }, // setter set: function (newValue) { var names = newValue.split(' ') this.firstName = names[0] this.lastName = names[names.length - 1] }}} ` ` `Copy the code

5.2 Watch Listener

The problem

How watch listens for changes inside an object.

Problem description

But most of the people I met didn’t give me the answer I expected. Some people would say “listen directly to OBJ”. Some people would say “listen directly to OBJ. So I only asked the listener, and only those who answered “deep” would ask about the role of immediate.

Hope the answer

If you only listen for a property change in OBj, you can directly listen for obj.key.

``` watch: { 'obj.question': function (newQuestion, oldQuestion) { this.answer = 'Waiting for you to stop typing... ' this.debouncedGetAnswer() } } ```Copy the code

If we listen deep to the entire OBJ

``` watch: { obj: { handler: function (newQuestion, oldQuestion) { this.answer = 'Waiting for you to stop typing... ' this.debouncedGetAnswer() }, deep: true, immediate: true } } ```Copy the code

What immediate does: The watch listens are not triggered when the value is bound for the first time. With immediate, the watch listens are triggered when the value is initially bound.

6, nextTick, do you know how it works?

Problem description

$nextTick used, what effect.

When asked this question, many people will say that they can handle asynchrony, but when asked why they use nextTick, what problems it solves, and what they will do without it, many people will not be able to tell.

Hope the answer

The deferred callback is performed after the next DOM update loop ends. Use this method immediately after modifying the data to get the updated DOM. When you change the data, you need to perform operations on the DOM immediately. In this case, the DOM is still obtained before the data is refreshed, which is not enough to meet the needs.

NextTick (function () {// DOM was updated}) // Use as a Promise (added since 2.1.0, NextTick () then(function () {// DOM was updated}Copy the code

The principle of

  • Promise
  • MutationObserver
  • setImmediate
  • If all else fails, use setTimeout

Defines an asynchronous method that clears the current queue by calling nextTick multiple times to store the method in the queue.

(See my other two columns about macro and microtasks and event loops.)

(As you can see from this, frameworks are ultimately a test of your native JavaScript skills.)

Common event modifiers

  • .stop: stops the bubble
  • .prevent: prevents the default behavior
  • Self: triggers only the binding element itself
  • .once: added in 2.1.4 and is triggered only once
  • Passive: added in 2.3.0. The default behavior of a rolling event (the rolling behavior) is triggered immediately and cannot be used with. Prevent
  • The sync modifier

As of 2.3.0, vue has reintroduced the.sync modifier, but this time it only exists as a compile-time syntactic sugar. It is extended to a V-on listener that automatically updates the properties of the parent component. The example code is as follows:

<comp :foo.sync="bar"></comp>
Copy the code

Will be extended to:

<comp :foo="bar" @update:foo="val => bar = val"></comp>
Copy the code

When a child component needs to update the value of foo, it needs to explicitly fire an update event:

this.$emit('update:foo', newValue)
Copy the code

How does Vue obtain the DOM

$refs. DomName = this.$refs. DomName = this.

<div ref="test"></div>

const dom = this.$refs.test
Copy the code

Can V-ON listen to multiple methods?

Yes, here’s an example:

<input type="text" v-on="{ input:onInput,focus:onFocus,blur:onBlur, }">
Copy the code

10. The difference between assets and static

Both are used to hold static resource files used in the project.

The difference:

Files in Assets will be packaged when running the NPM Run build, which means that they will be compressed in size, formatted in code, etc. It’s also going to be static after it’s packaged.

Static files are not packaged.

Suggestion: Place unprocessed files such as images in Assets and package them to reduce the size. If a third party introduces a resource file such as iconfont. CSS, you can put it in static because it has already been processed.

11. The vUE initialization page flashes

When using vue development, before vue initialization, because div is not controlled by vue, so we write code in the case of not parsed is easy to appear the phenomenon of flower screen, see similar to {{message}} words, although in general this time is very short, but we still need to let solve this problem.

First: add the following code to the CSS

[v-cloak] {
    display: none;
}
Copy the code

If the problem is not completely resolved, add style=”display: none;” to the root element. :style=”{display: ‘block’}”

Can Vue detect changes in an array item assigned directly?

Due to JavaScript limitations, Vue cannot detect the following array changes:

  • When you set an array entry directly using an index, for example:vm.items[indexOfItem] = newValue
  • When you change the length of an array, for example:vm.items.length = newLength

To solve the first problem, Vue provides the following operations:

Vue.set(vue.items, indexOfItem, newValue) // vue.set (vue.items, indexOfItem, newValue) $set(vm.items, indexOfItem, newValue) // array.prototype.splice vm.items.splice(indexOfItem, 1, indexOfItem) newValue)Copy the code

To solve the second problem, Vue provides the following operations:

// Array.prototype.splice
vm.items.splice(newLength)
Copy the code

What is your understanding of Vue’s life cycle?

(1) What is the life cycle?

There are eight stages:

  • beforeCreate

The data Observer is called after the instance is initialized and before the Event /watcher event is configured

  • created

Called immediately after the instance is created. At this point, the instance is complete: observer, property and method operations, watch/ Event event callback, the mount phase has not started, and the $EL property is not currently visible.

  • beforeMount

Called before the mount begins, the relevant render function is first called.

  • mounted

El is replaced by the newly created VM.$EL, and the hook is called after it is mounted to the instance. If the root instance mounts an element in the document, vm.$el is also in the document when mounted is called.

  • beforeUpdate

Called when data is updated, before the virtual DOM is rerendered and patched.

  • updated

This hook is called after the virtual DOM is rerendered and patched due to data changes.

  • beforeDestroyed

Called before the instance is destroyed, at which point the instance is still fully available.

  • destroyed

When called after the vue.js instance is destroyed, everything indicated by the vue.js instance will be unbound, all event listeners will be removed, and all child instances will be destroyed.

Add two cycles when using the keep-alive function of a component:

  • activatedinkeep-aliveCalled when the component is activated;
  • deactivatedinkeep-aliveCalled when the component is down.

When a dynamic component is wrapped,

caches inactive component instances instead of destroying them.

is an abstract component that does not render a DOM element itself and does not appear in the parent component chain.

When a component is switched within

, its lifecycle hook functions activated and deactivated are executed.

<keep-alive> < Component :is="view"></ Component ></ keep-alive> Copy codeCopy the code

Added a periodic hook: ErrorCaptured is called when an error from a descendant component is captured.

(2) Vue’s parent and child component lifecycle hook function execution order can be classified into the following four parts

  • Loading the render process

    Parent beforeCreate -> parent created -> parent beforeMount -> child beforeCreate -> child created -> child beforeMount -> Child Mounted -> parent

  • Child component update process

    Parent beforeUpdate -> child beforeUpdate -> child updated -> parent updated

  • Parent component update process

    Parent beforeUpdate -> Parent updated

  • Destruction of the process

    Parent beforeDestroy -> child beforeDestroy -> child Destroyed -> parent Destroyed

(3) In what lifecycle is the asynchronous request invoked?

This function can be called in the created, beforeMount, and Mounted hook functions, because data is created in these three hook functions and can be assigned to the data returned by the server. However, I recommend calling asynchronous requests in the created hook function, because calling asynchronous requests in the created hook function has the following advantages:

  • Faster access to server data, reduce page loading time;
  • SSR does not support beforeMount and Mounted hook functions, so it is placed in created to facilitate consistency.

(4) At what stage can I access the operation DOM?

Before the hook function mounted is called, Vue has already mounted the compiled template to the page, so you can access the DOM from mounted. The specific vUE life cycle diagram can be seen below, understand the operation of the entire life cycle of each stage, about the life cycle related interview questions will not be difficult to you.

(5) Can the parent component listen to the life cycle of the child component?

If the Parent component (Parent) and the Child component (Child) are mounted, the Parent component (Parent) hears that the mounted component is mounted. If the Parent component (Parent) hears that the Child is mounted, the Parent component (Child) hears that the mounted component is mounted.

// Parent.vue <Child @mounted="doSomething"/> // Child.vue mounted() { this.$emit("mounted"); } copy codeCopy the code

$emit triggers the parent component event manually. A simpler way is to listen when the parent component references the child component via @hook, as shown below:

// Parent. Vue <Child @hook: "></Child> doSomething() {console. '); }, // child.vue mounted(){console.log(' Child component triggers mounted hook function... '); }, // The output sequence is: // The child component triggers the Mounted hook function... // The parent listens to the Mounted hook function... Copy the codeCopy the code

Of course, @hook method can not only listen on mounted, other life cycle events, such as: created, updated, etc.

(6) What do you know about keep-alive?

Keep-alive is a component built into Vue that allows contained components to retain state and avoid rerendering. It has the following features:

  • Generally used in combination with routing and dynamic components to cache components;
  • Provide include and exclude attributes. Both support strings or regular expressions. Include means that only components with matching names will be cached.
  • The hook functions activated and deactivated are activated when the component is activated and deactivated when the component is removed.

14, Vue. The extend

1. Vue.extend(options) : The base Vue constructor

A parameter is an object that contains component options.

The data option is a special case, and in vue.extend () it must be a function in order to keep the data referenced.

<div id='app'> <span>MyApp</span> </div> <script> var Profile = Vue.extend({ template: '< p > goal: {{p1}},{{p2}}</p>', Data :function(){return {p1:' print record 1', p2:' print record 2'}}}) // Bind new Profile(). </script> Copy the codeCopy the code

2. Why extend?

In general, all our pages are managed with router, and components are locally registered through import, which also has some shortcomings.

For example: Suppose we need to dynamically render components from the interface? How to implement a window.alert() like prompt component that requires calling js?

3. How to construct a custom popover using extend

1. Write popover components

<template> <div v-if="show" ref="modal" class="ek-modal_wrap"> <div class="ek-modal-content"> <div class="modal-title-wrap"> <div class="modal-title">{{ title }}</div> <slot name="description"></slot> </div> <div class="modal-button"> <a v-if="confirmVisible" class="contral-btn confirm-btn" href="javascript:;" @click="confirm">{{ confirmText }}</a> <a v-if="cancleVisible" class="contral-btn cancle-btn" href="javascript:;" @click="cancle">{{ cancleText }}</a> </div> </div> </div> </template> <script> export default { data() { return { show: // confirmVisible: true, title: '', // confirmText: '', // confirmVisible: true, // onConfirm: $emit('confirm')}, $emit('confirm')}, $emit('confirm')}, $emit('confirm')}, $emit('confirm')}, $emit('confirm')}, $emit('confirm')}, $emit('confirm')}, $emit('confirm') { () = > {/ / cancel executive function enclosing $emit (' cancle ')}}}, the methods: { confirm() { this.onConfirm() this.close() }, cancle() { this.onCancle() this.close() }, Close () {this.show= false if (this.$refs.modal) {this.$refs.modal.remove() // Remove the current element directly when closing}}}} </script> <style lang="scss" scoped> .ek-modal_wrap { position: fixed; top: 0; left: 0; z-index: 999; width: 100%; height: 100%; font-size: 28px; Background: rgba(0, 0, 0, 0.7); .ek-modal-content { position: fixed; top: 50%; left: 50%; Min - width: 7.2 rem; overflow-x: hidden; overflow-y: hidden; text-align: center; background-color: white; Border - the top - left - the radius: 0.266667 rem. Border - top - right - the radius: 0.266667 rem. Border - bottom - right - the radius: 0.266667 rem. Border - bottom - left - the radius: 0.266667 rem. transform: translate(-50%, -50%); .modal-title-wrap { display: flex; flex-direction: column; flex-grow: 1; justify-content: center; min-height: 55px; padding: 0 20px; color: #333; } .modal-title { display: flex; flex-direction: column; flex-grow: 1; justify-content: center; min-height: 100px; margin-top: 30px; margin-bottom: 30px; font-weight: 600px; line-height: 50px; color: #333; } .modal-button { display: flex; line-height: 1; color: #333; border-top-color: #e7e7e7; border-top-style: solid; border-top-width: 1px; & > a { color: #333; } .contral-btn { flex-basis: 0%; flex-grow: 1; flex-shrink: 1; font-weight: 600px; line-height: 3; text-align: center; &.cancle-btn { border-left-color: #e7e7e7; border-left-style: solid; border-left-width: 1px; } } } } } </style>Copy the code

Step 2: Bind methods to vue’s prototype.

import Vue from 'vue'; import dialog from './components/Dialog.vue'; function showDialog(options) { const Dialog = Vue.extend(dialog); Const app = new Dialog().$mount(document.createElement('div')); For (let key in options) {app[key] = options[key]; } / / insert elements in the document in the body. The body. The appendChild (app) $el); } Vue.prototype.$showDialog = showDialog; // Put the method on the prototype.Copy the code

Step 3: Call the method in the Vue page

. Mounted () {console.log(this.$showDialog); This.$showDialog({title: 'test popover ', confirmText:' want popover to call correctly ', cancelVisible: false,}); },... Welcome to try itCopy the code

Custom instructions, from the bottom to solve the problem

What is a directive? An order is when your girlfriend points at you and says, “There’s the washboard. Get down on your knees. That’s an order!” . Just kidding. Programmers don’t have girlfriends.

In the previous section, we developed a loading component, and after the development, other development came up with two requirements when using it

  1. Can beloadingMount to an element, now can only be used in full screen
  2. You can use an instruction to mount a specified elementloading

If we need it, we do it. No word

1. Develop the V-loading command

Import Vue from 'Vue' import LoadingComponent from './loading' // Construct component subclass const LoadingContructor = with vue.extend Directive ('loading', {/** ** is called only once, when the directive is first bound to an element, @param {*} binding: {name:' directive name ', value: 'directive binding value ',arg: {name:' directive name ', value:' directive binding value ',arg: {name:' directive name ', value: 'directive binding value' } */ bind(el, binding) {const instance = new LoadingContructor({el: document.createElement('div'), data: {} }) el.appendChild(instance.$el) el.instance = instance Vue.nextTick(() => { el.instance.visible = binding.value }) }, * @param {*} el * @param {*} binding */ update(el, Binding) {// determine whether loading is displayed by changing the ratio if (binding. OldValue! == binding.value) {el.instance.visible = binding.value}}, /** * * @param {*} el */ unbind(el) {const mask = el.instance.$el if (mask.parentnode) { mask.parentNode.removeChild(mask) } el.instance.$destroy() el.instance = undefined } })Copy the code

2. Use instructions on elements

<template>
  <div v-loading="visible"></div>
</template>
<script>
export default {
  data() {
    return {
      visible: false
    }
  },
  created() {
    this.visible = true
    fetch().then(() => {
      this.visible = false
    })
  }
}
</script>
Copy the code

3. Which scenarios can be customized in the project

  1. Loading effect for a component

  2. Button level permission control V-permission

  3. Code burial point, which defines instructions according to the operation type

  4. Input The input box automatically gets the focus

  5. And so on…

16. Why is data a function?

Why does data in a component have to be a function and then return an object, whereas in a new Vue instance, data can be an object?

// data data() {return {message: "child component ", childName:this.name}} // new Vue new Vue({el: '#app', router, template: '<App/>', Components: {App}}) copy the codeCopy the code

If data is an object in a component, then there is no scope isolation. If data is a function in a component, then each instance can maintain a separate copy of the returned object. Data property values between component instances do not affect each other; Instances of new Vue, on the other hand, are not reused, so there is no reference object problem.

17. How does the V-Model work?

In our VUE project, we mainly use the V-Model directive to create two-way data binding on elements such as form input, Textarea, select, etc. We know that v-Model is essentially just syntax sugar. The V-Model internally uses different attributes for different input elements and throws different events:

  • Text and Textarea elements use the value attribute and input event;
  • Checkbox and radio use the Checked property and the change event;
  • The select field takes value as a prop and change as an event.

Take the input form element for example:

<input v-bind:value="something" v-on:input="something = $event.target.value">Copy the code

If in a custom component, v-Model will use a prop named value and an event named Input by default, as shown below:

</ModelChild> props:{value: String}, methods: </ModelChild> props:{value: String}, methods: {test1(){this.$emit('input', 'emit ')},},Copy the code

More elegant bidirectional data binding with.sync

In Vue, the props property is one-way. Updates to the parent prop flow down to the child component, but not vice versa. However, in some cases, we need to “bi-bind” the prop. Above, we mentioned the use of v-Model for bidirectional binding. However, there are times when we want a component to be able to “bidirectional bind” multiple data, whereas v-Model can only have one component (Vue3.0 can have multiple), when.sync is used.

. Similarities and Differences between sync and V-Model

Similarities:

  • Both are essentially syntactic sugar, designed to enable bidirectional binding of components to external data
  • Both are implemented through properties + events

Differences (personal point of view, if there is wrong, please comment below to point out, thank you) :

  • Only one component can be definedv-model, but you can define multiple.sync
  • v-modelwith.syncFor different event names,v-modelThe default event isinput, which can be configuredmodelTo modify,.syncEvent name Specifies the event nameUpdate: the property name

Custom. The sync

When developing a business, it is sometimes necessary to use a mask layer to prevent user behavior (more often using a mask layer +loading animation). The following is a custom. Sync to implement a mask layer

<! <template> <custom-overlay :visible.sync="visible" /> </template> <script> export default {data() {return { visible: false } } } </script>Copy the code

18. What are the communication methods between Vue components?

The communication between Vue components is one of the knowledge points often tested in the interview. This question is similar to the open question. The more ways you answer, the more points you will get, indicating that you are more proficient in Vue. Vue inter-component communication refers to the following three types of communication: parent-child communication, intergenerational communication, and sibling communication. We will introduce each type of communication and explain which type of inter-component communication this method can be applied to.

(1)props / $emitSuitable for communication between parent and child components

This method is the basis of Vue component. I believe that most students can hear it well, so I will not introduce it by example here.

(2)ref$parent / $childrenSuitable for communication between parent and child components

  • ref: If used on a normal DOM element, the reference refers to the DOM element. If used on a child component, the reference points to the component instance
  • $parent / $children: Access the parent/child instance

(3)EventBus ($EMIT / $ON)Suitable for communication between father and son, intergenerational and brother components

This method uses an empty Vue instance as the central event bus (event center), which can be used to trigger and listen for events, thus enabling communication between any component, including parent, generation, and sibling components.

(4)$attrs/$listenersSuitable for intergenerational communication

  • $attrs: contains feature bindings (except class and style) whose parent scope is not recognized (and retrieved) by prop. When a component does not declare any prop, all parent scope bindings (except class and style) are included and can be passedv-bind="$attrs"Pass in internal components. Usually used in conjunction with the inheritAttrs option.
  • $listeners: contains a V-on event listener in the parent scope (without.native modifier). It can go throughv-on="$listeners"Passing in internal components

(5)provide / injectSuitable for intergenerational communication

The ancestor component supplies variables via the provider, and the descendant component injects variables via the inject. The Provide/Inject API mainly solves the communication problem between cross-level components, but its use scenario is that the child component obtains the state of the parent component, and the cross-level components establish a kind of active provision and dependency injection relationship.

(6) Vuex is suitable for father and son, intergenerational, brother components communication

Vuex is a state management pattern developed specifically for vue.js applications. At the heart of every Vuex app is the store. A “store” is basically a container that contains most of the states in your app.

  • The state store of Vuex is responsive. When the Vue component reads the state from the store, if the state in the store changes, the corresponding component will be updated accordingly.
  • The only way to change the state in a Store is to explicitly commit the mutation. This makes it easy to track each state change.

19. Have you ever used Vuex?

Vuex is a state management mode developed specifically for vue.js applications.

At the heart of every Vuex app is the store. A “store” is basically a container that contains most of the states in your app.

(1) The state storage of Vuex is responsive. When the Vue component reads the state from the store, if the state in the store changes, the corresponding component will be updated accordingly.

(2) The only way to change the state in a Store is to explicitly commit the mutation. This makes it easy to track each state change.

It mainly includes the following modules:

  • State: A data structure that defines the State of the application, where you can set the default initial State.
  • Getters: To allow a component to get data from a Store, the mapGetters helper function simply maps getters in a Store to locally computed properties.
  • Mutation: is the only method to change the state in store and must be a synchronous function.
  • Action: Used for submitting mutations rather than directly changing state and can include any asynchronous operation.
  • Module: Allows a single Store to be split into multiple stores and stored in a single state tree.

How to batch use the Vuex getter property in components

Use the mapGetters helper function to mix getters into a Computed object using the object expansion operator

import {mapGetters} from 'vuex' export default{ computed:{ ... mapGetters(['total','discountTotal']) } }Copy the code

3. Mutation is repeatedly used in components

MapMutations auxiliary function, which is used in the component

import { mapMutations } from 'vuex' methods:{ ... mapMutations({ setNumber:'SET_NUMBER', }) }Copy the code

Then call this.setnumber (10) rather than this.store.com MIT (‘SET_NUMBER’,10)

4. What is the difference between mutation and action

  • The action commits the mutation instead of directly changing the state. Mutation can change the state directly

  • An action can contain any asynchronous operation. Mutation can only be a synchronous operation

  • Different submission methods

    Action is committed with this.store.dispatch(‘ACTION_NAME’,data). The mutation is submitted using this.store.com MIT (‘SET_NUMBER’,10)

  • The receiving parameters are different. The first parameter of mutation is state, while the first parameter of action is context, which contains

    {state, // equal to store.state, if in the module is local state rootState, // equal to store.state, Commit, // equivalent to store.com MIT dispatch, // equivalent to store.dispatch getters, // equivalent to store.dispatch getters, // Equivalent to store.getters rootGetters // equivalent to store.getters, exists only in modules}

How to use the Vuex value of state on the V-model?

You need to convert using the computed computing attribute.

<input v-model="message">
// ...
computed: {
    message: {
        get () {
            return this.$store.state.message
        },
        set (value) {
            this.$store.commit('updateMessage', value)
        }
    }
}
Copy the code

20. Have you ever used Vue SSR? Tell me something about the SSR?

Vue.js is a framework for building client-side applications. By default, the Vue component can be exported to the browser to generate and manipulate the DOM. However, you can also render the same component as HTML strings on the server side, send them directly to the browser, and finally “activate” those static tags as a fully interactive application on the client side.

SSR roughly means that vue renders the entire HTML fragment of the tag on the client side and completes the work on the server side. The HTML fragment formed by the server side is directly returned to the client side. This process is called server side rendering.

The advantages and disadvantages of server-side rendering SSR are as follows:

(1) Advantages of server-side rendering:

  • Better SEO: Because the content of the SPA page is obtained through Ajax, and the search engine crawl tool will not wait for Ajax asynchronous completion of the page to crawl the content, so in the SPA is to crawl the page through Ajax to get the content; SSR is directly returned by the server to the rendered page (the data is already contained in the page), so search engine crawler tools can crawl the rendered page;
  • Faster content arrival time (faster first screen loading) : SPA will wait for all Vue compiled JS files to be downloaded before rendering the page. It takes a certain amount of time to download files, so the first screen rendering needs a certain amount of time. SSR renders the page directly by the server and returns to display, without waiting to download JS file and render again, so SSR has faster content arrival time;

(2) Disadvantages of server-side rendering:

  • More development constraints: for example, server-side rendering only supports the beforCreate and Created hook functions, which results in some external extension libraries requiring special treatment to run in server-side rendering applications. And unlike SPA, a completely static single-page application that can be deployed on any static file server, the server-side rendering application needs to be in the Node.js Server runtime environment;
  • More server load: Rendering a full application in Node.js is obviously much more CPU-intensive than a server that only serves static files, so if you expect to use it in high traffic environments, Prepare your server load and use your caching strategy wisely.

If there is no SSR development experience of students, you can refer to the author of another SSR practice article “Vue SSR pit journey”, SSR project construction and with the source code.

21. Routing related

1. How to define nested routines?

In a real project we will encounter multiple layers of nested components, but how do we implement nested components? Therefore, we need to use the children configuration in the VueRouter parameter, so that the routing can be well nested. Index.html, with only one route egress

<div id="app"> <! </router-view> </router-view> </div> Copy the codeCopy the code

Main.js, the redirect of the route, will display the home component as soon as the page loads, because the redirect is directed to the home component. The redirect must be the same as the path. Children is a child route. Of course, child routes can be nested in the child route.

Import Vue from 'Vue' import VueRouter from 'vue-router' vue.use (VueRouter) import home from "./home. Vue" Import game from "./game.vue" const routes = [{path: "/", redirect: "/home"},// "/home", component: home, children: [ { path: "/home/game", component: Const router = new VueRouter({routes}) new Vue({el: '#app', data: {}, methods: {}, router}) copy the codeCopy the code

The exit of the child route must be in the parent route. Otherwise, the child route cannot be displayed.

How to define the dynamic route of vue-router? How to obtain the dynamic parameters passed?

In the index.js file in the router directory, add /:id to the path attribute. The params.id of the Router object is used to get the dynamic parameters

The arguments passed in with the query method are accepted with this.$route.query

Arguments passed in using params are accepted using this.$route.params

Navigation hook for vue-router

The common one is router.beforeeach (to,from,next), which makes permission judgment before jumping. There are three:

BeforeEach (to,from,next), beforeResolve, afterEach BeforeRouteEnter, beforeRouteUpdate, beforeRouteLeave 3. Independent route exclusive component: beforeEnter

To indicates the destination route object to be entered. From indicates the route that the current navigation is leaving. Next means you must use this function to get to the next route, or you will be intercepted if you don’t use it.

4. The difference between router and route

Route indicates that name, path, Query, and params can be obtained from the current Router jump object

Router is a VueRouter instance, and if you want to navigate to a different URL, use the router.push method

Vue.$router

$router.push() // There is no record this.$router.replace() //n can be positive or negative. Window.history.go (n) this.router.go (n) $router.go(n)Copy the code

Vue.$route

Indicates the current route object. The attributes are as follows: Name: indicates the route name. Path: the path; Query: pass the received value of the parameter; Params: the received value of the passed parameter

$route.query. Id: gets the parameter passed by params or /:id. This.$route.queryCopy the code

5. Routes are loaded on demand

As the number of functional modules in the project increases, the number of imported files increases dramatically. If nothing is done, the first screen loading will be quite slow, and this is where the route on demand loading comes in.

Webpack < 2.4 {path:'/', name:'home', Resolve =>require(['@/components/home'],resolve)} webpack> 2.4 {path:'/', name:'home', components:()=>import('@/components/home') }Copy the code

The import() method is proposed by ES6, and dynamic loading returns a Promise object. The argument to the then method is the module to which it was loaded. Similar to node.js’s require method, the main import() method is loaded asynchronously.

6. How many vue-router routing modes are available?

Vue-router has three routing modes: Hash, History, and Abstract. The corresponding source code is as follows:

switch (mode) { case 'history': this.history = new HTML5History(this, options.base) break case 'hash': this.history = new HashHistory(this, options.base, this.fallback) break case 'abstract': this.history = new AbstractHistory(this, options.base) break default: if (process.env.NODE_ENV ! == 'production') { assert(false, `invalid mode: ${mode}`) } }Copy the code

The three routing modes are described as follows:

  • Hash: The HASH value of the URL is used for routing. Support for all browsers, including those that do not support the HTML5 History Api;

  • History: Relies on the HTML5 History API and server configuration. See the HTML5 History mode;

  • Supports all JavaScript runtime environments, such as the Node.js server side. If no browser API is found, the route is automatically forced into this mode.

7. How do you implement the hash and history routing modes commonly used in Vue-Router?

(1) Implementation principle of the hash mode

Early implementations of front-end routing were based on location.hash. The implementation is simple. The value of location.hash is what follows the # in the URL. For example, the following site has a location.hash value of ‘#search’ :

https://www.word.com#search
Copy the code

The implementation of the Hash routing mode is based on the following features:

  • The hash value in the URL is only a state of the client. That is, when a request is sent to the server, the hash part is not sent.
  • Each change in the hash value adds a record to the browser’s access history. So we can use the browser’s back and forward buttons to control the hash switching;
  • You can use the a tag and set the href attribute. When the user clicks the tag, the HASH value of the URL will change. Or use JavaScript to assign loaction.hash and change the HASH value of the URL.
  • We can use the HashChange event to listen for the hash value to jump (render) to the page.

(2) The implementation principle of history mode

HTML5 provides the History API to implement URL changes. The two most important apis are history.pushState() and history.repalcestate (). These two apis allow you to manipulate the browser’s history without refreshing it. The only difference is that the former adds a new history, while the latter directly replaces the current history, as follows:

window.history.pushState(null, null, path);
window.history.replaceState(null, null, path);
Copy the code

The implementation of the History routing pattern is based on the following features:

  • The pushState and repalceState apis operate to implement URL changes;
  • We can use popState events to listen for url changes and jump to the page (rendering).
  • History.pushstate () or history.replacestate () do not trigger popState events, so we need to manually trigger the page jump (render).

22. Related to vUE project configuration

1. Description of SRC directory in vue.cli project

  1. assetsFolders store static resources.
  2. componentsStorage components;
  3. routerDefine routing configuration;
  4. viewIs the view;
  5. app.vueIs an application master component;
  6. main.jsYes entry file

2. Configure the Vue-LIC3 scaffold (vue.config.js)

PublicPath: The type is String

Default: ‘/’

The base URL for deploying the application package. By default, the Vue CLI assumes that your application is deployed on the root path of a domain name, such as www.my-app.com/. If the application is deployed in a…

ProductionSourceMap: Do not allow project source mapping files to be generated while packaging, which can significantly reduce package size in production environments

AssetsDir: the directory (relative to outputDir) where the generated static resources (js, CSS, img, fonts) will be placed. The default is ”,

IndexPath: Specifies the output path (relative to outputDir) of the generated index.html. It could be an absolute path. The default is’ index.html ‘

LintOnSave: Whether to use ESLint every time you save. This is syntax strict and can be used by students who want to use it themselves

css

{extract: true, sourceMap: false,// extract: true, sourceMap: false,// extract: true False,// open CSS Modules for all CSS and its preprocessing files. // This option does not affect the '*.vue' file. },Copy the code

DevServer (how to avoid cross-domain calls in the vue.js development environment)

Local development server configuration, here directly paste my common configuration, in the way of comments

DevServer: {// configure the development server host: "0.0.0.0", // whether to enable hot loading, that is, whether to refresh the browser to see the new code effect every time you update the code hot: true, // Service start port port: Open: false, // Configure HTTP proxy: {"/ API ": {/ / if the address is http://192.168.0.118:9999/api1 ajax request then you can use in jajx/API/api1 path, its request path will parse / / http://192.168.0.118:9999/api1, Of course, on your browser to http://localhost:8080/api/api1; Target: "http://192.168.0.118:9999", / / whether to allow cross-domain, here is will play a role in the development environment, but in a production environment, or by the background to deal with, so don't too care about changeOrigin: true, pathRewrite: {/ / the redundant path set to '" API ":" "}}, "/ api2" : {/ / you can configure multiple agents, matching what kind of analytical method that is used on the target: "http://api2", / /... }}}, copy the codeCopy the code

pluginOptions

This is an object that does not perform any schema validation, so it can be used to pass any third-party plug-in options, such as:

{// define a global less file and put the common style variables in it so that you don't have to re-reference 'style-resources-loader' every time you use it: {preProcessor: 'less', patterns: ['./ SRC /assets/public.less']}} Copy the codeCopy the code

chainWebpack

Is a function that receives an instance of a ChainableConfig based on webpack-chain. Allows for more granular changes to the internal WebPack configuration. Such as:

ChainWebpack (config) {// add a path alias to the assets/img/menu/ directory. If the full path to the require ("/assets/img/menu/img1. PNG ") / / to introduce under different level is too inconvenient, Config.resolve. alias // Add multiple aliases to support the chain call.set("assets", path.join(__dirname, "/ SRC/assets")). The set (" img ", path. Join (__dirname, "/ SRC/assets/img/menu")) / / introduction pictures just the require (" img/img1. PNG "); Can}Copy the code

4. What is Axios

Axios is a module used in vue2.0 to replace the vue-resource-js plug-in. It is a module that requests backend resources

Usage scenarios

The encapsulation of Axios is mainly used to help us intercept requests and responses.

In the interception of requests, we can carry userToken, POST request header, SERIalization of DATA submitted by QS to POST, etc.

In the interception of the response, we can do the uniform processing of the error according to the status code and so on.

The unified management of the AXIOS interface is a necessary process when doing projects. This makes it easier for us to manage our interface so that we don’t have to go back to our business code to modify it when the interface is updated.

5. What is vue-loader

Vue -loader is a loader that parse. vue files and converts template/js/style to javascript modules. Using this Vue-Loader, javascript can write EMAScript6 syntax, style styles can apply SCSS or less, template can add Jade syntax…

23. Code optimization

1. The page needs to import multiple components, how to avoid writing one at a time, such as in a directory all components are imported at once, require.context()

1. Scenario: If multiple components need to be imported to the page, the original writing method is:

import titleCom from '@/components/home/titleCom'
import bannerCom from '@/components/home/bannerCom'
import cellCom from '@/components/home/cellCom'
components:{titleCom,bannerCom,cellCom}
Copy the code

2. This is a lot of repetitive code, which can be written using require.context

const path = require('path')
const files = require.context('@/components/home', false, /\.vue$/)
const modules = {}
files.keys().forEach(key => {
  const name = path.basename(key, '.vue')
  modules[name] = files(key).default || files(key)
})
components:modules
Copy the code

This method can be used no matter how many components are introduced into the page

2.components and Vue.component

Components: Locally registered components

Var props = {props: [], template: '<div><p>{{extendData}}</ div>', var props: [], template: '<div><p>{{extendData}}</ div>', var extendData}}</ div> Function () {return {extendData: 'This is a locally registered component ',}},}; var Profile = Vue.extend(obj); New Vue({el: '#app', components:{'component-one':Profile, 'component-two':obj}});Copy the code

Vue.component: global registration component

1. Register (name) the extended instance constructor generated by vue.extend as a global component. The argument can be an instance of the vue.extend () extension or an object (which automatically calls the extend method) 2. Two arguments, a component name, and an EXTEND constructor or object

Var props = {props: [], template: '<div><p>{{extendData}}</ div>', var props: [], template: '<div><p>{{extendData}}</ div>', var extendData}}</ div> Function () {return {extendData: 'this is the component registered by Vue.component into vue.extend ',}},}; var Profile = Vue.extend(obj); //2. Register component method 1: pass vue.extend constructor Vue.component('component-one', Profile) //2. To register a component, simply pass Vue.component('component-two', obj) //3. Mount new Vue({el: '#app'}); // get the registered component(always return constructor) var oneComponent=Vue.component('component-one'); Console. log(oneComponent===Profile)//true, the returned Profile constructorCopy the code

3. Scenarios where mixins are used in a project

Scenario: Some components have duplicate JS logic, such as verify the phone captcha, parse time, etc. Mixins can implement this mixins value is an array

Var mixin={data:{mixinData:' I am mixin's data'}, created:function(){console.log(' this is mixin's created'); }, methods:{getSum:function(){console.log(' this is the method in getSum in mixin '); }} var mixinTwo={data:{mixinData:' mixinTwo '}, created:function(){console.log(' this is mixinTwo created'); }, methods:{getSum:function(){console.log(' this is the method in mixinTwo's getSum '); }}} var vm=new Vue({el:'#app', data:{mixinData:' I am Vue instance data'}, created:function(){console.log(' this is Vue instance created'); }, methods:{getSum:function(){console.log(' this is the method of getSum in the vue instance '); }}, mixins:[mixin,mixinTwo]}Copy the code

For related conflicts in mixed components and master components:

1. For methods, methods in the main component overwrite methods mixed into the component (with the same name).

2. If the lifecycle is the same, the names in the same lifecycle are merged into one. If the names in the corresponding lifecycle are the same, the names are also overwritten

3. Hook functions in the mixed object are called before hook functions in the main component;

4. With the same hook function, console is called before the hook function in the main component.

The difference with vuex

After the above example, the difference between them should be:

Vuex: used for state management. Variables defined in vuex can be used and modified in each component. If the value of this variable is changed in any component, the value of this variable will also be changed in other components.

Mixins: You can define common variables that are used in each component. Once introduced into the component, the variables are independent of each other, and the changes to their values do not affect each other in the component.

4.extends

Extends is similar to mixins except that the parameters it receives are simple option objects or constructors, so extends extends only one component at a time

Var extendData ={data:{extendData:' I am the data of extend '}, created:function(){console.log(' this is the creation of extend '); }, methods:{getSum:function(){console.log(' this is the method in extend's getSum '); }} var mixin={data:{mixinData:' I am mixin's data'}, created:function(){console.log(' this is mixin's created'); }, methods:{getSum:function(){console.log(' this is the method in getSum in mixin '); }}} var vm=new Vue({el:'#app', data:{mixinData:' I am Vue instance data'}, created:function(){console.log(' this is Vue instance created'); }, methods:{getSum:function(){console.log(' this is the method of getSum in the vue instance '); }}, mixins:[mixin], extends:extend})Copy the code

5.Vue.use()

When we use an element, we import it first, then use() to register the component and trigger the install method. This is often used in component calls; Multiple registrations of the same plug-in are automatically organized.

28. What optimizations have you made for the Vue project?

If you have not made a summary of Vue project optimization, you can refer to another article “Vue Project Performance Optimization – Practice Guide” by the author of this paper. This article mainly introduces how to optimize Vue project from 3 big aspects and 22 small aspects in detail.

1. Code level optimization

1.1 V-IF and V-show are used in different scenarios

V-if is true conditional rendering; V-show is much simpler, the element is always rendered regardless of the initial condition, and simply switches based on the DISPLAY property of the CSS.

Therefore, V-if is suitable for scenarios where conditions are rarely changed at runtime and do not need to be switched frequently; V-show is suitable for scenarios that require very frequent switching conditions.

1.2 Use scenarios for computed and Watch

Computed: The value of computed is cached. Only when the value of the dependent attribute changes, the value of computed is recalculated the next time the value of computed is obtained.

Watch: More of a “watch” function, similar to the listening callback of some data, every time the listening data changes, the callback will be executed for subsequent operations;

Application scenario:

  • Use Computed when you need to perform numeric computations that depend on other data because the caching feature of computed avoids having to recalculate the value every time it is fetched.

  • Watch should be used when we need to perform an asynchronous or expensive operation when data changes. Using the Watch option allows us to perform an asynchronous operation (access an API), limits how often we perform the operation, and sets the intermediate state until we get the final result. These are things that computational properties can’t do.

In v-for traversal, we must add key to item and avoid using v-if at the same time

(1) V-for traversal must add key to item

In the traversal rendering of the list data, it is necessary to set a unique key value for each item, so that the internal mechanism of vue. js can accurately find the list data. When the state is updated, the new state value is compared to the old state value, locating diff more quickly.

(2) V-for traversal avoids using v-if at the same time

V-for has a higher priority than V-if. If you need to traverse the entire array every time, it will affect the speed, especially if you need to render a small portion of the array. Replace it with computed if necessary.

Recommendation:

<ul>
  <li
    v-for="user in activeUsers"
    :key="user.id">
    {{ user.name }}
  </li>
</ul>
computed: {
  activeUsers: function () {
    return this.users.filter(function (user) {
	 return user.isActive
    })
  }
}
Copy the code

1.4 Long list performance optimization

Vue will hijack the data through object.defineProperty to enable the view to respond to changes in the data. However, sometimes our components are just displaying the data without any changes, so we don’t need Vue to hijack our data. In the case of large data display, This can significantly reduce component initialization time, so how do we prevent Vue from hijacking our data? You can freeze an Object by using the object.freeze method. Once the Object is frozen, it cannot be modified.

export default { data: () => ({ users: {} }), async created() { const users = await axios.get("/api/users"); this.users = Object.freeze(users); }};Copy the code

1.4. Object. Freeze Usage Scenario

Vue is a new feature in ES5 that can freeze an object and prevent it from being modified. Vue 1.0.18+ supports this feature. Vue does not translate getters and setters for objects frozen in data or vuex with freeze. Note: the freeze is only a single property within the freeze. The reference address can still be changed

List: object.freeze ([{value: 1}, {value: 1}, {value: 1}) }, mounted () {this.list[0].value = 100; This.list = [{value: 100}, {value: 200}]; this.list = Object.freeze([ { value: 100 }, { value: 200 } ]); }})Copy the code

1.5 Destruction of events

When a Vue component is destroyed, it automatically cleans up its connections to other instances and unbinds all of its instructions and event listeners, but only the component’s own events. If we use addEventListene and other methods in JS, we need to manually remove the listener for these events when the component is destroyed, so as to avoid memory leak. For example:

created() {
  addEventListener('click', this.click, false)
},
beforeDestroy() {
  removeEventListener('click', this.click, false)
}
Copy the code

1.6. Image resources are loaded lazily

For pages with too many pictures, in order to speed up the page loading speed, so many times we need to do not load the images that do not appear in the visual area of the page, wait until the scrolling to the visual area to load. This will greatly improve the page loading performance and improve the user experience. We used Vue’s Vue-Lazyload plugin for this project:

(1) Install the plug-in

npm install vue-lazyload --save-dev
Copy the code

(2) Import and use in the entry file man.js

import VueLazyload from 'vue-lazyload'
Copy the code

Then use it directly in vue

Vue.use(VueLazyload)
Copy the code

Or add custom options

Use (VueLazyload, {preLoad: 1.3, error: 'dist/error. PNG ', loading: 'dist/ load.gif ', attempt: 1})Copy the code

(3) In the vue file, change the SRC attribute of img tag to V-lazy, so as to change the image display mode to lazy loading display:

<img v-lazy="/static/img/1.png">
Copy the code

This is a simple example of vue-lazyload. To see more options, check out vue-lazyload’s Github address.

1.7. Routes are loaded lazily

Vue is a single-page application, and many routes may be imported. In this way, the files packaged by WebPCAk are large. When entering the home page, too many resources are loaded, and the page will appear white screen, which is not good for user experience. It would be more efficient if we could split the components of different routes into separate code blocks and then load the components when the route is accessed. This will greatly speed up the first screen, but may slow down the rest of the page.

Lazy route loading:

const Foo = () => import('./Foo.vue')
const router = new VueRouter({
  routes: [
    { path: '/foo', component: Foo }
  ]
})
Copy the code

1.8 Introduction of third-party plug-ins on demand

We often need to introduce third-party plug-ins in our projects. If we directly introduce the whole plug-in, the volume of the project will be too large. We can use Babel-plugin-Component and then only introduce the required components to reduce the volume of the project. The following is an example of introducing the Element-UI component library in a project:

(1) First, install babel-plugin-Component:

npm install babel-plugin-component -D
Copy the code

(2) Then change.babelrc to:

{
  "presets": [["es2015", { "modules": false }]],
  "plugins": [
    [
      "component",
      {
        "libraryName": "element-ui",
        "styleLibraryName": "theme-chalk"
      }
    ]
  ]
}
Copy the code

(3) Introduce some components in main.js:

import Vue from 'vue';
import { Button, Select } from 'element-ui';

 Vue.use(Button)
 Vue.use(Select)
Copy the code

1.9. Optimize the performance of infinite lists

If your application has very long or infinitely scrolling lists, you need to use windowing techniques to optimize performance, rendering only a small area of content, reducing the time to re-render components and create DOM nodes. You can optimize this infinite list scenario by looking at the following open source projects vue-virtual-scl-List and Vue-virtual-Scroller.

(2) Optimization at the Webpack level

  • Webpack compresses images
  • Reduce redundant code from ES6 to ES5
  • Extract common code
  • Template precompile
  • Extract the CSS for the component
  • Optimize SourceMap
  • Build result output analysis
  • Compilation optimization for the Vue project

(3) Optimization of basic Web technology

  • The gZIP compression function is enabled

  • Browser cache

  • The use of CDN

  • Use Chrome Performance to find Performance bottlenecks

24, vUE principle part

1. Do you know the compiling principle of Vue template

Before understanding the Vue render function, we need to understand the overall vue process (as shown in the figure above).

The figure above should give you an idea of how a Vue component works.

  • Templates are compiled to generate AST trees
  • The AST tree generates Vue’s render function
  • The render function combines data to generate Virtual DOM Node(vNode) trees
  • New UI after Diff and Patch (real DOM rendering)

In this picture, we need to understand the following concepts:

  • Template, Vue template is pure HTML, based on Vue template syntax, can be more convenient to deal with the relationship between data and UI interface
  • AST is short for Abstract Syntax Tree. Vue parses THE HTML template into AST, performs some optimized tag processing on AST, and extracts the largest static Tree, so that the Virtual DOM directly skips the following Diff
  • The render function is used to generate the Virtual DOM. Vue recommends using templates to build our application, and Vue eventually compiles the templates to render functions in the underlying implementation. Therefore, if we want more control, we can write the render function directly.
  • Virtual DOM: Virtual DOM
  • Watcher, each Vue component has a correspondingwatcher, it will be in the componentrenderCollect the data that the component depends on, and trigger the component to re-render when the dependency is updated. Vue will automatically optimize and update the DOM that needs to be updated

2. What is MVVM?

Model-view-viewmodel (MVVM) is a software architecture design pattern developed by Ken Cooper and Ted Peters, Microsoft ARCHITECTS for WPF and Silverlight, as a way to simplify user interface event-driven programming. Published by John Gossman (also WPF and Silverlight architect) on his blog in 2005

MVVM is derived from the classic Model-View-Controller (MVC) pattern. The emergence of MVVM promotes the separation of front-end development and back-end business logic, and greatly improves the efficiency of front-end development. The core of MVVM is the ViewModel layer. It is like a value converter, responsible for the transformation of data objects in the Model to make the data easier to manage and use, the layer up to two-way data binding with the view layer, and down to the Model layer through the interface request for data interaction, the role of up and down. As shown in the figure below:

(1) View layer

View is the View layer, the user interface. The front end is built primarily out of HTML and CSS.

(2) Model

Model refers to the data Model, which generally refers to the business logic processing and data manipulation carried out by the back end, and the API interface provided by the back end for the front end.

(3) ViewModel layer

A ViewModel is a view data layer that is generated and maintained by the front-end developer organization. In this layer, the front-end developer transforms the Model data retrieved from the back end and re-wraps it to generate the View data Model that the View layer expects to use. It is important to note that the data Model encapsulated by the ViewModel includes the state and behavior of the view, whereas the data Model of the Model layer contains only the state, such as what this section of the page shows, what happens when the page loads, what happens when you click on this section, What happens when this piece scrolls is all part of the view behavior (interaction), the view state and behavior is encapsulated in the ViewModel. This encapsulation allows the ViewModel to fully describe the View layer.

The MVVM framework implements bidirectional binding, so that the contents of the ViewModel are displayed in the View layer in real time, and front-end developers no longer need to inefficient and cumbersome manipulation of the DOM to update the View. The MVVM framework has done the dirty part, and we developers only need to handle and maintain the ViewModel. Updating the data view will automatically update accordingly. In this way, the View layer presents not the Model layer’s data, but the ViewModel’s data, and the ViewModel is responsible for the interaction with the Model layer. This completely decouples the View layer and the Model layer. This decoupling is crucial. It is an important part of the implementation of the anterior and posterior separation scheme.

We follow a Vue example to illustrate the specific implementation of MVVM, have Vue development experience of students should be clear:

(1) View layer

<div id="app">
    <p>{{message}}</p>
    <button v-on:click="showMessage()">Click me</button>
</div>
Copy the code

(2) ViewModel layer

Var app = new Vue({el: '#app', data: {// used to describe view status message: 'Hello Vue! ',}, methods: {// To describe view behavior showMessage(){let vm = this; alert(vm.message); } }, created(){ let vm = this; ({url: '/your/server/data/ API ', success(res){vm.message = res; }}); }})Copy the code

(3) Model layer

{
    "url": "/your/server/data/api",
    "res": {
        "success": true,
        "name": "IoveC",
        "domain": "www.cnblogs.com"
    }
}
Copy the code

3. How does Vue implement bidirectional data binding?

Vue.js uses data hijacking combined with publist-subscriber mode. It hijacks setters and getters of each property through object.defineProperty (), publishes messages to subscribers when data changes, and triggers the corresponding listener callback. The main steps are as follows:

You need to recurse through the data object, including the property of the child property object, with the setter and getter so that if you assign a value to this object, you trigger the setter, and you can listen for changes in the data

2. Compile parses the template instruction, replaces variables in the template with data, and then initializes the rendering page view, binds the corresponding nodes of each instruction to update functions, and adds subscribers who listen to data. Once the data changes, the view will be notified and updated

3. Watcher subscribers are the communication bridge between Observer and Compile, and do the following: (1) Add yourself to the attribute subscriber (DEp) when you instantiate yourself; (2) you must have an update() method; (3) You can call your update() method and trigger the callback bound in the Compile (Compile) when you are notified of the attribute change.

4. MVVM, as the entry of data binding, integrates Observer, Compile and Watcher. It listens to its own model data changes through Observer, and parse the compilation template instructions through Compile. Finally, use Watcher to build a communication bridge between Observer and Compile, to achieve data change -> view update; View Interactive Changes (INPUT) -> Bidirectional binding effect of data Model changes.

How does the Vue framework implement listening on objects and arrays?

Object.defineproperty () hijack the data, but object.defineProperty () can only hijack attributes, not the whole Object. Similarly, you can’t hijack an array, but we know from using the Vue framework that Vue can detect changes to objects and arrays (partial method operations), so how does it work? Let’s look at the relevant code as follows:

/** * Observe a list of Array items. */ observeArray (items: Array<any>) { for (let i = 0, l = items.length; i < l; I ++) {observe(items[I]) // observe(items[I])}} /** * Recurse through attributes */ let childOb =! Shallow && Observe (VAL) // Observe function indicates the change of the monitored dataCopy the code

By looking at the Vue source section above, we can know that the Vue framework can also listen to objects and arrays (partial method operations) using object.defineProperty () by traversing groups and recursively traversing objects.

5, Proxy and Object. DefineProperty comparison

Proxy has the following advantages:

  • A Proxy can directly listen on objects rather than properties;
  • Proxy can directly listen for array changes.
  • Proxy has up to 13 intercepting methods, not limited to apply, ownKeys, deleteProperty, has and so on, which Object. DefineProperty does not have;
  • Proxy returns a new Object, we can only operate on the new Object to achieve the purpose, but object.defineProperty can only traverse the Object properties directly modify;
  • Proxy as a new standard will be the focus of browser vendors continued performance optimization, that is, the legendary new standard performance dividend;

The advantages of object.defineProperty are as follows:

  • It is compatible with IE9, but Proxy has browser compatibility issues and cannot be polished with Polyfill, so Vue’s authors declare that they will have to wait until the next major release (3.0) to rewrite it with Proxy.

$set() = $set() = $set();

Due to the limitations of modern JavaScript, Vue cannot detect the addition or removal of object properties. Since Vue performs getter/setter transformations on the property when initializing the instance, the property must exist on the data object for Vue to convert it to responsive. Vue provides vue.set (object, propertyName, value)/vm.$set (object, propertyName, value) to add responsive properties to objects. How does the framework itself implement this?

We view the corresponding Vue source: Vue/SRC/core/instance/index. Js

export function set (target: Array<any> | Object, key: any, val: any): If (array.isarray (target) && isValidArrayIndex(key)) {// Modify the Array length, Target. Length = math.max (target.length, key) // Trigger the response target.splice(key, 1, key) Val) return val} if (key in target &&! (key in Object.prototype)) { target[key] = val return val } const ob = (target: Any).__ob__ // Target itself is not responsive data, directly assign if (! DefineReactive (ob.value, key, val) ob.dep.notify() return val}Copy the code

$set = $set; $set = $set; $set = $set;

  • If the target is an array, use the array’s splice method to trigger the corresponding expression.

  • If the target is an object, the attribute is read for existence, the object is responsive, and finally, if the attribute is to be responsive, it is handled responsively by calling defineReactive (which means that when Vue initializes the object, Method to dynamically add getters and setters to an Object property using object.defineProperty)

25. Virtual DOM

1. Realization principle of virtual DOM?

The realization principle of virtual DOM mainly includes the following three parts:

  • Using JavaScript object to simulate real DOM tree, real DOM abstract;
  • Diff algorithm – compare the difference between two virtual DOM trees;
  • Pach algorithm – Applies the differences between two virtual DOM objects to the real DOM tree.

If you are not familiar with the above three parts, you can check out the article “Deep Analysis: The Virtual DOM at the core of Vue” written by the author.

2. What is the function of key in Vue?

Because manipulating the DOM in the browser is expensive. Frequent manipulation of the DOM can cause performance problems. This is where the virtual Dom comes in.

The Virtual DOM of Vue2 draws lessons from the implementation of snABbDOM, an open source library.

The essence of a Virtual DOM is to use a native JS object to describe a DOM node. Is a layer of abstraction from the real DOM. (This is the VNode class in the source code, which is defined in SRC /core/vdom/vnode.js.)

The mapping from VirtualDOM to the real DOM goes through the create, diff, and patch phases of the VNode.

“The purpose of a key is to reuse as many DOM elements as possible.”

Only when the order of the nodes in the old and new children is different, the best operation is to move the element to achieve the update.

You need to save the mapping between the nodes of the old and new children so that you can find the reusable nodes in the nodes of the old children. Key is the unique identifier of the node in children.

The key in Vue is the unique identifier of the vnode in Vue. The diff operation is faster and more accurate

More accurate: since there is no in-place reuse with the key, this can be avoided in the sameNode function a.keey === B.keey comparison. So it will be more accurate.

Faster: Use the key’s uniqueness to generate a map object to obtain the corresponding node, faster than traversal mode, source code as follows:

function createKeyToOldIdx (children, beginIdx, endIdx) {
  let i, key
  const map = {}
  for (i = beginIdx; i <= endIdx; ++i) {
    key = children[i].key
    if (isDef(key)) map[key] = i
  }
  return map
}
Copy the code

3. What are the pros and cons of virtual DOM?

Advantages:

  • Guaranteed performance lower limit: The virtual DOM of the framework needs to be adapted to any operation that may be generated by the upper-layer API. The implementation of some DOM operations must be universal, so its performance is not optimal. But performance is much better than rough DOM manipulation, so the framework’s virtual DOM at least ensures that you can still provide decent performance without having to manually optimize.
  • No manual manipulation of the DOM: We no longer need to manually operate the DOM, just need to write the code logic of the View-Model, according to the virtual DOM and data two-way binding, help us to update the View in a predictable way, greatly improve our development efficiency;
  • Cross-platform: The VIRTUAL DOM is essentially a JavaScript object, and the DOM is strongly platform dependent. In contrast, the virtual DOM can be more easily cross-platform, such as server rendering, WEEX development, and so on.

Disadvantages:

  • Unable to perform extreme optimization: Although the virtual DOM + reasonable optimization is sufficient to meet the performance requirements of most applications, the virtual DOM cannot perform targeted extreme optimization in some applications with high performance requirements.

29. What do you know about the upcoming Vue3.0 features?

Vue 3.0 is on its way to release. The goal of Vue 3.0 is to make the Vue core smaller, faster, and more powerful. As a result, Vue 3.0 adds the following new features:

(1) Changes in monitoring mechanisms

3.0 will bring a proxy-based observer implementation that provides full language coverage for reactive tracking. This removes many of the limitations of the object.defineProperty-based implementation in Vue 2:

  • Only properties can be monitored, not objects

  • Detect the addition and removal of attributes;

  • Detect array index and length changes;

  • Supports Map, Set, WeakMap, and WeakSet.

The new Observer also provides the following features:

  • A public API for creating An Observable. This provides a simple and lightweight cross-component state management solution for small to medium scale scenarios.
  • Lazy observation is adopted by default. In 2.x, no matter how large the equation data is, it will be observed at startup. If your data set is large, this can cause significant overhead at startup. In 3.x, only the data used to render the first visible part of the application is observed.
  • More precise notification of changes. In 2.x, forcing a new property to be added with ue. Set causes watcher dependent on the object to be notified of the change. In 3.x, only watcher that depends on a particular property will be notified.
  • Immutable Observable: We can create “immutable” versions of values (even nested properties) unless the system temporarily “unlocks” them internally. This mechanism can be used to freeze prop transfers or changes outside of the Vuex state tree.
  • Better debugging: We can use the new renderTracked and renderTriggered hooks to track exactly when and why components are being rerendered.

(2) Template

There are no major changes to the template, only the scope slots. The 2.x mechanism causes scope slots to be changed and the parent component will be rerendered, while 3.0 changes the scope slots to function mode, which only affects the child component’s rerendering and improves the rendering performance.

Also, vue3.0 will make a series of changes to the render function to make it easier to use the API directly to generate vdom.

(3) Object type component declaration

Components in vue2.x pass in a list of options via declarations. TypeScript uses decorators, which are cumbersome to implement. 3.0 changes the way components are declared to be class-like, making it easier to work with TypeScript.

In addition, vue source code is written in TypeScript instead. In fact, when the function of the code is complex, it is necessary to have a static type system to do some management. Now that VUe3.0 is fully rewritten in TypeScript, it makes it easier to integrate exposed apis with TypeScript. Static type systems are indeed necessary for the maintenance of complex code.

(4) Other changes

The changes in VUe3.0 are comprehensive, only the three main areas are covered above, and there are a few other changes:

  • Support for custom renderers allows WEEX to be extended by custom renderers rather than forking the source code.
  • Support for Fragment (multiple root nodes) and Protal (rendering components in other parts of the DOM) components for special scenarios.
  • Treeshaking optimized for more built-in functionality.

30. Tell me about the biggest pit you’ve ever stepped on with a Vue frame. How was it solved?

Please feel free to share your experiences in the comments section to help prevent others from stepping in the pit again

1. After the package, the file, picture, background image resource does not exist or the path is wrong

The default value is’/’, which is the root path. Therefore, the public path of the packaged resource is static in the root directory. The problem is that if your resources are not stored in the root directory of the server, but in a folder like mobile under the root directory, the packaged path will conflict with the path in your code, and the resources will not be found.

So, to solve this problem, you can change the above path from the root of ‘/’ to the relative path of ‘./ ‘when packaging.

In this case, the packaged image, js and so on is the path'. / static/img/asc. JPG 'Relative paths like that, so no matter where you put it, you can’t go wrong. However, there is always but ~~~~~ everything is ok here, but the path of the background image is still wrong. Because now the relativities are going to bestatic/css/Under folderstatic/img/xx.jpgBut in factstatic/css/It’s not in the folderstatic/img/xx.jpg, i.e.,static/css/static/img/xx.jpgIt doesn’t exist. The current CSS file path relative to. To solve this problem, add a common path to the background image in our CSS'.. /.. / 'That is, let him go back up two levels to the sumindex.htmlThe location of the corresponding file, then the relative path at this pointstatic/img/xx.jpgI can find the right resource. If you want to change the public path of the background image, you can use loader to parse the background image. Open the utils file in the Build folder and go to the exports.cssLoaders function.

Find this location and add a configuration, as shown in the red box above, to change its public path to two levels up and back. So pack again see next, ok!

2. Problem with large.map files generated after packaging

After the project is packaged, the code is compressed and encrypted. If an error occurs when the project is run, the output error message will not tell you exactly where the error occurred. A file with the.map suffix, like unencrypted code, can output exactly which line and which column is wrong. You can set it not to generate such a file. However, we don’t need.map files in the build environment, so we can do this without generating them when packaging:

In the config/index.js file, set productionSourceMap: false to not generate the.map file

3. Routing problem

Error with route TypeError: Cannot read property ‘matched’ of undefined

If you find new Vue() in the entry file main.js, you must use the name of the router. You cannot change the router to router or any other alias

/routers/ route. js' new Vue({el: '#app', router, // the name must use router render: h => h(app)});Copy the code

Vue router-link is useful on computer, but it doesn’t work on Android

Vue routing on Android is not correct. The Babel problem is rectified by installing the Babel polypill plug-in

The event registered on the router-link in Vue2 is invalid

< li > < the router - link to = "/ one" @ click = "change (' color1)" "class =" {' bgred: FFF [' color1]} "> page a < / router - the link > < / li >Copy the code

Using the @ click. Native. Cause: The router-link blocked the click event. Native means listening directly to a native event

RouterLink does not work in Internet Explorer and Firefox (routes do not jump)

  • Use only the A tag, not the button tag

  • Use the button label and the router. navigate method

    Admin

Use the

<button type="button" clrDropdownItem (click)="gotoAdmin()"> Admin </button> import { Router } from '@angular/router'; . export class MainComponent { constructor( private router: Router ) {} gotoAdmin() { this.router.navigate(['/admin']); }}Copy the code

Finishing the

1, 30 Vue interview questions, including detailed explanation (covering introduction to master, self-test Vue mastery) (juejin. Cn)

2. Problems and solutions in Vue (Update) (juejin.cn)

3, the history of the strongest VUE summary — interview development all depends on it (juejin.cn)