preface

In this paper, the high frequency of Vue related interview questions and with detailed answer difficulty is divided into three types of simple medium difficult, you can look at the answer to test their own Vue level ha, if the principle of students interested in welcome to see xiaobian handwritten Vue source series articles If you have a different view of the answer to the students welcome to comment area to add discussion at the end of welcome to click on the link to join the shark brother front group push discussion technology fish for help can be (into the group for free to get Vue2 source mind map ha)

If you think this article is helpful, please remember to like it. Thank you very much!


simple

1 differences between MVC and MVVM

MVC

MVC full name is Model View Controller, Model (Model)- View (View)- Controller (Controller) abbreviation, a software design Model

  • Model: The part of the application that processes the logic of the application data. Typically, model objects are responsible for accessing data in the database
  • View: The part of the application that handles the display of data. Typically, views are created from model data
  • Controller: The part of the application that handles user interaction. Typically, the controller is responsible for reading data from the view, controlling user input, and sending data to the model

The idea behind MVC is that the Controller is responsible for displaying the Model data in the View. In other words, the Controller is responsible for assigning the Model data to the View.

MVVM

The VM class is added to MVVM

  • The ViewModel layer: It does two things to achieve bidirectional binding of data. One is to convert the model into the view, which is to convert the data passed in the back end into the page that you see. The way to do this is: data binding. The second is to convert [view] into [model], which is to convert the page you see into data at the back end. DOM event listener.

The biggest difference between MVVM and MVC is: When a property of the Model changes, we don’t have to manually manipulate the Dom element to change the View display. Instead, when we change the property, the View layer display will automatically change (corresponding to the Vue data-driven idea).

Overall, MVVM is much simpler than MVC, not only simplifying business and interface dependencies, but also solving the problem of frequently updating data without having to manipulate DOM elements with selectors. Because in MVVM, the View is not aware of the Model and the View is not observed by the Model and ViewModel, this low coupling pattern improves code reusability

Note: Vue does not fully follow the MVVM philosophy, as the website notes

So the question is why do officials say that Vue does not fully follow MVVM thinking?

  • The strict MVVM requirement that the View should not communicate with the Model directly, but Vue provides the $refs property so that the Model can directly manipulate the View, which violates this rule, so Vue is not fully compliant with MVVM.

2 Why is data a function

The data in the component is written as a function, and the data is defined as the return value of the function, so that each time the component is reused, a new copy of data is returned. This is similar to creating a private data space for each component instance and having each component instance maintain its own data. However, simply writing the data in object form causes all component instances to share the same data, resulting in a result that all components will change

3 What are the communication methods of the Vue component

  1. The props and $emit parent components pass data to the child component through prop, and the child component passes data to the parent component through the $emit trigger event

  2. $parent,$children gets the current component’s parent and the current component’s children

  3. $listeners -> A->B->C. Vue 2.4 started with $attrs and $Listeners to address this issue

  4. The parent component provides variables via provide, and the child component injects variables via inject. (Not officially recommended for use in real business, but commonly used when writing component libraries)

  5. $refs Gets the component instance

  6. EnvetBus sibling component data transfer in this case can use the event bus mode

  7. Vuex state management

4. What are the lifecycle methods of Vue

BeforeCreate is called after instance initialization and before data Observer and Event /watcher event configuration. During the current phase, data and methods on Data, Methods, Computed, and Watch are not accessible

The created instance is called after it has been created. At this stage, the instance has completed the following configuration: Data Observer, operation of properties and methods, and watch/ Event event callback. There is no $EL, and if you really want to interact with the Dom, you can access it via vm.$nextTick

BeforeMount is called before the mount begins: the relevant render function is called for the first time.

Mounted Occurs after the Dom is mounted. In this stage, real Dom is mounted, data is bi-directional bound, and Dom nodes can be accessed

BeforeUpdate Is called when data is updated and occurs before the virtual DOM is rerendered and patched. You can further change the state in this hook without triggering additional rerendering

Updated occurs after the update is complete. The Dom of the component in the current phase has been updated. It is important to avoid changing the data during this time, as this could result in an infinite loop of updates, and the hook is not called during server-side rendering.

BeforeDestroy Called before the instance is destroyed. At this step, the instance is still fully available. This is where we can put the finishing touches, such as a cleanup timer.

Destroyed Vue is called after the instance is destroyed. When called, everything indicated by the Vue instance is unbound, all event listeners are removed, and all child instances are destroyed. This hook is not called during server-side rendering.

Activated keep-alive only, called when a component is activated

Deactivated keep-alive only, called when a component is destroyed

At what step is the asynchronous request initiated?

Asynchronous requests can be made in the created, beforeMount, and Mounted hook functions because data is already created in these three hook functions and can be assigned to the data returned by the server.

If the asynchronous request does not need to depend on the Dom, it is recommended to call the asynchronous request in the created hook function, because calling the asynchronous request 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.

5 The difference between v-if and V-show

V-if is converted to a ternary expression during compilation and is not rendered if the condition is not met.

V-show will be compiled as an instruction, and the control style will hide the corresponding node if the condition is not met (display:none)

Usage scenarios

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

Display: None, visibility:hidden, and opacity:0

Talk about vue built-in instructions

7 How to understand Vue unidirectional data flow

Data is always passed from the parent component to the child component. The child component has no right to modify the data passed from the parent component. It can only request the parent component to modify the original data. 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.

Note: The development environment will be warned if the child component directly binds a prop from the parent component to the V-Model

If you really want to change the parent component’s prop value, you can define a variable in data and initialize it with the prop value. Then use $emit to notify the parent component to change the value

8 Differences between Computed and Watch and application scenarios

Computed is a computed property that depends on other properties to compute values, and computed values are cached and returned only when the computed value changes, and it can set getters and setters.

The watch listens to a change in value and executes a callback, in which some logical operations can be performed.

Computed attributes are commonly used in template rendering, where a value depends on other reactive objects or even computed attributes. The listen attribute is suitable for observing a change in a value to complete a complex piece of business logic

Calculate the attributes of the principle of detailed portal

Listening attribute principle detail portal

9 Why is v-if and V-for not recommended together

Do not use v-for and V-if in the same tag because v-for is parsed before V-if. If you need to use it at the same time, you can consider writing the way to calculate the properties.


medium

Vue2.0 principles of responsive data

The whole idea is data hijacking + observer

Objects are internally hijacked (only existing properties are hijacked) using object.defineProperty via defineReactive methods, and arrays are overridden by array methods. When the page uses the corresponding property, each property has its own DEP property, which holds the watcher that it depends on (dependency collection). When the property changes, the corresponding watcher is notified to update (dispatch updates).

The relevant code is as follows

class Observer {
  / / observations
  constructor(value) {
    this.walk(value);
  }
  walk(data) {
    // All properties on the object are observed in turn
    let keys = Object.keys(data);
    for (let i = 0; i < keys.length; i++) {
      let key = keys[i];
      letvalue = data[key]; defineReactive(data, key, value); }}}// Object.defineProperty Data hijack core compatibility in IE9 and above
function defineReactive(data, key, value) {
  observe(value); // Recursive key
  // -- if value is still an object, it will continue through odefineReactive until value is not an object
  / / think? If the Vue data is nested too deeply >> performance will suffer
  Object.defineProperty(data, key, {
    get() {
      console.log("Get value");

      // We need to do a dependency collection process
      return value;
    },
    set(newValue) {
      if (newValue === value) return;
      console.log("Setting values");
      // We need to do a distribution update processvalue = newValue; }}); }export function observe(value) {
  // Hijack properties if the object or array is passed
  if (
    Object.prototype.toString.call(value) === "[object Object]" ||
    Array.isArray(value)
  ) {
    return newObserver(value); }}Copy the code

Responsive data theory detail portal

11 How does Vue detect array changes

Array considering performance reasons not defineProperty an array of each item to intercept, choosing instead to seven kinds of array (push, shift, pop, splice, unshift, sort, reverse) method rewrite (AOP sliced thought)

So changing the index and length of an array in Vue cannot be monitored. You need to change the array through the above 7 mutation methods to trigger the watcher corresponding to the array to update

The relevant code is as follows

// src/obserber/array.js
// Keep the array prototype
const arrayProto = Array.prototype;
// Then we inherit arrayMethods from the array prototype
// Here's slicing oriented programming (AOP) -- dynamically extending functionality without breaking encapsulation
export const arrayMethods = Object.create(arrayProto);
let methodsToPatch = [
  "push"."pop"."shift"."unshift"."splice"."reverse"."sort",]; methodsToPatch.forEach((method) = > {
  arrayMethods[method] = function (. args) {
    // The results of the prototype method are retained
    const result = arrayProto[method].apply(this, args);
    // This sentence is the key
    {a:[1,2,3]} {a:[1,2,3]} {a:[1,2,3]}} {a:[1,2,3]}} {a:[2,3]}} {a:[1,2,3]}}
    const ob = this.__ob__;

    // A new operation is added to the array
    let inserted;
    switch (method) {
      case "push":
      case "unshift":
        inserted = args;
        break;
      case "splice":
        inserted = args.slice(2);
      default:
        break;
    }
    // If there is a new element inserted, an array is called observeArray of the Observer instance to observe each item in the array
    if (inserted) ob.observeArray(inserted);
    // We can also detect changes in the array and trigger an update to the view -- the source code will be revealed later
    return result;
  };
});
Copy the code

An array of observation principles detailed portal

Have you used VUe3.0? How much do you know

  • Vue3.x uses Proxy instead of vue2.x’s object.defineProperty

  • X Using Composition API Setup is an option added to Vue3. It is an entry point to the Composition API within a component.

  • Template syntax change Slot Named slot syntax custom directive V-Model Upgrade

  • Suspense supports fragments (multiple root nodes) and Protal (building content that is rendered in other parts of the DOM) components for specific scenarios. Treeshaking optimized for more built-in functionality.

A summary of new Vue3.0 features and experience with portal

13 Vue3.0 and 2.0 response principle difference

Use Proxy instead of Object. DefineProperty in Vue3. Because Proxy can directly listen for changes in objects and arrays, there are up to 13 intercepting methods.

The relevant code is as follows

import { mutableHandlers } from "./baseHandlers"; // Proxy related logic
import { isObject } from "./util"; // Tool method

export function reactive(target) {
  // Create different response objects based on different parameters
  return createReactiveObject(target, mutableHandlers);
}
function createReactiveObject(target, baseHandler) {
  if(! isObject(target)) {return target;
  }
  const observed = new Proxy(target, baseHandler);
  return observed;
}

const get = createGetter();
const set = createSetter();

function createGetter() {
  return function get(target, key, receiver) {
    // Radiate the obtained value
    const res = Reflect.get(target, key, receiver);
    console.log("Attribute fetching", key);
    if (isObject(res)) {
      // If the value obtained is an object type, return a proxy object for the current object
      return reactive(res);
    }
    return res;
  };
}
function createSetter() {
  return function set(target, key, value, receiver) {
    const oldValue = target[key];
    const hadKey = hasOwn(target, key);
    const result = Reflect.set(target, key, value, receiver);
    if(! hadKey) {console.log("Properties added", key, value);
    } else if (hasChanged(value, oldValue)) {
      console.log("Property value modified", key, value);
    }
    return result;
  };
}
export const mutableHandlers = {
  get, // This method is called when the property is fetched
  set, // This method is called when a property is modified
};
Copy the code

14 The sequence of execution of parent-child component lifecycle hook functions for Vue

  • 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

Father father beforeUpdate – > updated

  • Destruction of the process

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

15 What is the virtual DOM? What are the pros and cons

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, which is a layer of abstraction of the real DOM.

Advantages:

  1. 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.

  2. 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;

  3. 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:

  1. 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.

  2. When rendering a large number of DOM for the first time, the extra layer of virtual DOM computation is slower than innerHTML insertion.

16 v – model principle

V-model is just grammatical sugar

Internally, v-Model uses different properties for different input elements and throws different events:

  • Text and Textarea elements use value property and input events;
  • Checkbox and radio use checked Property and change events;
  • The select field takes value as a prop and change as an event.

Note: For languages that require input methods (such as Chinese, Japanese, Korean, etc.), you will find that the V-Model will not be updated when the input method is used to compose text.

On the normal label

    <input v-model="sth" />  // This row is equal to the next row
    <input v-bind:value="sth" v-on:input="sth = $event.target.value" />
Copy the code

On the components

<currency-input v-model="price"></currentcy-input>
<! </currency-input> --> <currency :value="price" @input="price = arguments[0]"></currency-input> -->

<! -- Subcomponent definition -->
Vue.component('currency-input', {
 template: `
  <span>
   <input
    ref="input"
    :value="value"
    @input="$emit('input', $event.target.value)"
   >
  </span>
 `,
 props: ['value'],
})

Copy the code

17 V-for why do we add key

Without keys, Vue uses an algorithm that minimizes dynamic elements and tries to modify/reuse elements of the same type in place as much as possible. The key is the unique token of the vnode in the Vue. With this key, we can perform diff operations more accurately and quickly

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: Using the uniqueness of the key to generate a map object to obtain the corresponding node, faster than the traversal method

The relevant code is as follows

// Check whether the label and key of two vnodes are the same. If they are the same, the same vnode is reused in place
function isSameVnode(oldVnode, newVnode) {
  return oldVnode.tag === newVnode.tag && oldVnode.key === newVnode.key;
}

{'a':0,'b':1} = 'a' in the first position and 'b' in the second position
function makeIndexByKey(children) {
  let map = {};
  children.forEach((item, index) = > {
    map[item.key] = index;
  });
  return map;
}
// The generated mapping table
let map = makeIndexByKey(oldCh);
Copy the code

Diff algorithm details the portal

18 Vue Event binding principle

Native event bindings are bound to real elements through addEventListener, and component event bindings are implemented through Vue’s custom $ON. If you want to use native events on a component, you need to add the.native modifier, which is equivalent to using a parent component as a normal HTML tag and then adding native events.

$on and $EMIT are based on the published_subscribe mode, maintaining an event center. When on, events are stored in the event center by name, called subscriber, and then emit publishes the corresponding events to execute the corresponding listener in the event center

Handwritten publish subscribe principle Portal

19 Vue-router What is the route hook function and in what order

This section describes the execution process of route hooks. The hook functions are global guard, route guard, and component guard

Complete navigation parsing process:

  1. Navigation is triggered.
  2. Call the beforeRouteLeave guard in the deactivated component.
  3. Calls the global beforeEach guard.
  4. Call the beforeRouteUpdate guard (2.2+) in the reused component.
  5. Call beforeEnter in the route configuration.
  6. Resolve the asynchronous routing component.
  7. Call beforeRouteEnter in the activated component.
  8. Call the global beforeResolve guard (2.5+).
  9. Navigation is confirmed.
  10. Call the afterEach hook globally.
  11. Triggers a DOM update.
  12. Call the callback function passed to next in the beforeRouteEnter guard, and the created component instance is passed as an argument to the callback function.

20 vue-router What is the dynamic route? What is the problem

It is often necessary to map all routes that a pattern matches to the same component. For example, we have a User component that is used to render all users with different ids. So, we can use “dynamic segment” in the vue-router routing path to achieve this effect:

const User = {
  template: "<div>User</div>"};const router = new VueRouter({
  routes: [
    // Dynamic path parameters start with a colon
    { path: "/user/:id".component: User },
  ],
});
Copy the code

Problem: What should I do if route parameters are invalid because the Vue-Router component is reused?

Solution:

1. Use watch to listen for route parameters and then send the request

watch: { // Use watch to listen for routing changes

 "$route": function(){
 this.getData(this.$route.params.xxx); }}Copy the code

2. Use :key to prevent “reuse”

<router-view :key="$route.fullPath" />
Copy the code

Talk about my personal understanding of VUEX

Vuex is a global state management system specifically for VUE for data sharing, data caching, etc. (Cannot persist, the internal core principle is to create a global instance new Vue)

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.

22 What can I do if data is lost during THE Vuex page refresh

You need to do THE VUEX data persistence generally use the local storage scheme to save the data you can design your own storage scheme or you can use third-party plug-ins

It is recommended to use the Vuex-Persist plug-in, which is a plug-in created for persistent vuex storage. You do not need to manually access the storage, but directly save the state to a cookie or localStorage

Why does Vuex divide modules and add namespaces

Modules: By using a single state tree, all the state of an application is concentrated into one large object. When the application becomes very complex, the Store object can become quite bloated. To solve this problem, Vuex allows us to split the store into modules. Each module has its own state, mutation, action, getter, and even nested submodules.

Namespaces: By default, actions, mutations, and getters within a module are registered in the global namespace — this enables multiple modules to respond to the same mutation or action. If you want more encapsulation and reuse, you can make your module namespaced: true by adding namespaced: true. When a module is registered, all its getters, actions, and mutations are automatically named according to the registered path of the module.

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

SSR is also called server rendering, which means that Vue renders the tags to HTML on the client side and then returns the HTML directly to the client side.

Advantages:

SSR has better SEO and loads faster on the first screen

Disadvantages: Development conditions are limited, server rendering only supports beforeCreate and Created hooks, special treatment is required when we need some external extension libraries, server rendering applications also need to be in the node.js runtime environment.

There will be a greater load on the server

What design patterns are used in VUE

1. Factory pattern – Pass in parameters to create an instance

The virtual DOM returns the Vnode of the underlying label and the component Vnode depending on the parameter

2. Singleton pattern – The entire program has one and only one instance

The plug-in registration method of vuex and VuE-Router install determines that if an instance exists in the system, it will be returned directly

3. Publish-subscribe pattern (VUE event mechanism)

4. Observer Mode (responsive data principle)

5. Decorator: (@decorator usage)

6. Policy Pattern A policy pattern is when an object has a behavior that can be implemented differently in different scenarios – such as a combination policy of options

. Additional models are welcome

What Vue performance optimizations have you made

This only lists the performance optimization for Vue. The performance optimization of the whole project is a big project and can be written in another article on performance optimization

  • Don’t go too deep in the object hierarchy, or performance will suffer
  • Do not put data that does not require responsiveness in data (use object.freeze () to freeze data)
  • V-if and V-show are used in different scenarios
  • Computed and Watch are used in different scenarios
  • For v-for traversal, you must add a key, preferably an ID, and avoid using v-if at the same time
  • Big data list and table performance optimization – virtual list/virtual table
  • To prevent internal leaks, global variables and events are destroyed after the component is destroyed
  • Lazy image loading
  • The route was loaded lazily. Procedure
  • The on-demand introduction of third-party plug-ins
  • Use keep-Alive cache components appropriately
  • Anti-shaking, throttling application
  • Server render SSR or pre-render

difficult

27 Scenarios and principles of vue. mixin

In daily development, we often encounter the same or similar code in different components. The functions of these codes are relatively independent, which can be extracted from the common business logic through Vue’s mixin function. The principle is similar to “object inheritance”. The mergeOptions method is called to merge when the component is initialized, using policy mode to merge the different properties. When components and mixins have options with the same name, these options are “merged” in the appropriate manner.

The relevant code is as follows

export default function initMixin(Vue){
  Vue.mixin = function (mixin) {
    // Merge objects
      this.options=mergeOptions(this.options,mixin) }; }};// src/util/index.js
// Define the lifecycle
export const LIFECYCLE_HOOKS = [
  "beforeCreate"."created"."beforeMount"."mounted"."beforeUpdate"."updated"."beforeDestroy"."destroyed",];// Merge policies
const strats = {};
// Mixin core method
export function mergeOptions(parent, child) {
  const options = {};
  // Go over the father
  for (let k in parent) {
    mergeFiled(k);
  }
  // The father has no son
  for (let k in child) {
    if (!parent.hasOwnProperty(k)) {
      mergeFiled(k);
    }
  }

  // True merge field method
  function mergeFiled(k) {
    if (strats[k]) {
      options[k] = strats[k](parent[k], child[k]);
    } else {
      // Default policyoptions[k] = child[k] ? child[k] : parent[k]; }}return options;
}
Copy the code

Vue. Mixin details the principle of portal

28 nextTick Application scenarios and Principles

The callbacks in nextTick are delayed callbacks that are executed after the next DOM update loop ends. Use this method immediately after modifying the data to get the updated DOM. The main idea is to call asynchronous methods to execute nextTick wrapped methods in a microtask-first way

The relevant code is as follows

let callbacks = [];
let pending = false;
function flushCallbacks() {
  pending = false; // Restore flag to false
  // Execute the callbacks in sequence
  for (let i = 0; i < callbacks.length; i++) { callbacks[i](); }}let timerFunc; // Define an asynchronous method with graceful degradation
if (typeof Promise! = ="undefined") {
  // If promise is supported
  const p = Promise.resolve();
  timerFunc = () = > {
    p.then(flushCallbacks);
  };
} else if (typeofMutationObserver ! = ="undefined") {
  // MutationObserver is an asynchronous method that listens for dom changes
  let counter = 1;
  const observer = new MutationObserver(flushCallbacks);
  const textNode = document.createTextNode(String(counter));
  observer.observe(textNode, {
    characterData: true}); timerFunc =() = > {
    counter = (counter + 1) % 2;
    textNode.data = String(counter);
  };
} else if (typeofsetImmediate ! = ="undefined") {
  // If neither of the preceding supports setImmediate
  timerFunc = () = > {
    setImmediate(flushCallbacks);
  };
} else {
  // The last degradation is to use setTimeout
  timerFunc = () = > {
    setTimeout(flushCallbacks, 0);
  };
}

export function nextTick(cb) {
  // In addition to rendering watcher, the nextTick is collected into the array along with the user's own manual call
  callbacks.push(cb);
  if(! pending) {// If nextTick is called multiple times, the flag will be changed to false after the asynchronous queue is cleared
    pending = true; timerFunc(); }}Copy the code

NextTick principle detail portal

29 Keep-alive Scenarios and principles

Keep-alive is a component built into Vue that caches components without uninstalling the current component when the component is switched.

  • Two common attributes, include/exclude, allow components to conditionally cache.

  • Two life cycles, activated and deactivated, are used to determine whether the current component is active.

  • Keep-alive also uses the LRU(Least Recently Used) algorithm, which selects the most recently unused components for elimination.

The relevant code is as follows

export default {
  name: "keep-alive".abstract: true.// Abstract component

  props: {
    include: patternTypes, // The component to cache
    exclude: patternTypes, // Components to exclude
    max: [String.Number].// Maximum number of caches
  },

  created() {
    this.cache = Object.create(null); {a:vNode,b:vNode}
    this.keys = []; // Cache component's key set [a,b]
  },

  destroyed() {
    for (const key in this.cache) {
      pruneCacheEntry(this.cache, key, this.keys); }},mounted() {
    // Dynamic listener include exclude
    this.$watch("include".(val) = > {
      pruneCache(this.(name) = > matches(val, name));
    });
    this.$watch("exclude".(val) = > {
      pruneCache(this.(name) = >! matches(val, name)); }); },render() {
    const slot = this.$slots.default; // Get the slot default value for the package
    const vnode: VNode = getFirstComponentChild(slot); // Get the first child component
    constcomponentOptions: ? VNodeComponentOptions = vnode && vnode.componentOptions;if (componentOptions) {
      // check pattern
      constname: ? string = getComponentName(componentOptions);const { include, exclude } = this;
      // Disable the cache
      if (
        // Not included Not included(include && (! name || ! matches(include, name))) ||// Excluded
        (exclude && name && matches(exclude, name))
      ) {
        // Return the virtual node
        return vnode;
      }

      const { cache, keys } = this;
      constkey: ? string = vnode.key ==null
          ? // same constructor may get registered as different local components
            // so cid alone is not enough (#3269)
            componentOptions.Ctor.cid +
            (componentOptions.tag ? ` : :${componentOptions.tag}` : "")
          : vnode.key;
      if (cache[key]) {
        // Find the cache by key to get the instance
        vnode.componentInstance = cache[key].componentInstance;
        // make current key freshest
        remove(keys, key); // Delete the key from the array by LRU algorithm
        keys.push(key); // Put it at the end of the array
      } else {
        cache[key] = vnode; // If you don't find it, save it
        keys.push(key); // Put it at the end of the array
        // Prune simple entry // Delete the 0th item from the array if it exceeds the maximum size
        if (this.max && keys.length > parseInt(this.max)) {
          pruneCacheEntry(cache, keys[0], keys, this._vnode);
        }
      }

      vnode.data.keepAlive = true; // Indicates that the virtual node has been cached
    }
    // Return the virtual node
    return vnode || (slot && slot[0]); }};Copy the code

What is the LRU algorithm?

The core idea of LRU is that if the data has been accessed recently, it has a higher chance of being accessed in the future, so we insert the component key that hit the cache back into the end of this. Keys. In this way, the data in the header of this. Let’s delete the data that is least likely to be accessed in the future, which is the first cached component in this.keys.

30 Vue.set Principle

Those of you who are familiar with the reactive principle of Vue know that there are two situations where you modify the data and Vue does not trigger an update of the view

1. Add new properties to the instance after it has been created (add properties to reactive objects)

2. Change the array index directly to change the array value

Vue.set, or $set, works like this

For reactive data we added an __ob__ attribute to both the object and the array itself, which represents the Observer instance. When adding a nonexistent property to an object, the new property is first tracked responsively and then the watcher collected by the dep of the object __ob__ is triggered to update it. When changing the array index, we call the splice method of the array itself to update the array

The relevant code is as follows

export function set(target: Array | Object, key: any, val: any) :any {
  // If it's an array, call the splice method we overwrote (so we can update the view)
  if (Array.isArray(target) && isValidArrayIndex(key)) {
    target.length = Math.max(target.length, key);
    target.splice(key, 1, val);
    return val;
  }
  // If it is a property of the object itself, add it directly
  if (key intarget && ! (keyin Object.prototype)) {
    target[key] = val;
    return val;
  }
  const ob = (target: any).__ob__;

  // There is no need to define a responsive property if it is not responsive
  if(! ob) { target[key] = val;return val;
  }
  // Define the attribute as responsive
  defineReactive(ob.value, key, val);
  // Notify view updates
  ob.dep.notify();
  return val;
}
Copy the code

Responsive data theory detail portal

31 Vue.extend Functions and principles

Extend uses the base Vue constructor to create a “subclass”. A parameter is an object that contains component options.

The constructor is the core API of the Vue component. The idea is that it returns a subclass of Vue using prototype-inherited methods and merges the options of the passed component with the options of the parent class using mergeOptions

The relevant code is as follows

export default function initExtend(Vue) {
  let cid = 0; // Unique identification of the component
  // Create a subclass that inherits from the Vue parent class to facilitate property extension
  Vue.extend = function (extendOptions) {
    // Create the subclass constructor and call the initialization method
    const Sub = function VueComponent(options) {
      this._init(options); // Call the Vue initialization method
    };
    Sub.cid = cid++;
    Sub.prototype = Object.create(this.prototype); // The subclass prototype points to the superclass
    Sub.prototype.constructor = Sub; //constructor refers to itself
    Sub.options = mergeOptions(this.options, extendOptions); // Merge your options with those of your parent class
    return Sub;
  };
}
Copy the code

Vue component principle detail portal

Have you ever written a custom instruction

Directives are essentially decorators that are vUE extensions to HTML elements that add custom functionality to HTML elements. When vue compiles the DOM, it finds the instruction object and executes the method associated with the instruction.

A custom instruction has five life cycles (also called the hook function) : bind, inserted, Update, componentUpdated, and unbind

1. Bind: called only once, the first time a directive is bound to an element. This is where you can do one-time initialization. 2. Inserted: Called when the bound element is inserted into the parent node (only ensures that the parent exists, but not necessarily that it has been inserted into the document). 3. Update: called when the template to which the element is bound is updated, regardless of whether the binding value has changed. Unnecessary template updates can be ignored by comparing binding values before and after updates. 4. ComponentUpdated: Called when the template to which the bound element belongs completes an update cycle. 5. Unbind: called only once, when the instruction is unbound from the element.Copy the code

The principle of

1. When the AST syntax tree is generated, the directives are added to the current element

2. Generate the directive code using the genDirectives

3. Extract the hook of the instruction to CBS before patch, and call the corresponding hook during patch

4. When executing the hook function corresponding to the instruction, the method defined by the corresponding instruction is called

33 What are the Vue modifiers

Event modifier

  • .stop prevents the event from propagating further
  • . Prevent Prevents the label default behavior
  • .capture uses the event capture pattern, where events triggered by the element itself are processed before being passed to the internal element for processing
  • Self fires the handler only if the event. Target is the current element itself
  • The.once event will be triggered only once
  • .passive tells the browser that you do not want to prevent the default behavior of the event

Modifier for v-model

  • Lazy, with this modifier, is converted to resynchronization at the change event

  • .number Automatically converts the user input value to a numeric type

  • Trim Automatically filters the first and last Spaces entered by the user

Modifiers for keyboard events

  • .enter
  • .tab
  • .delete (capture “Delete” and “backspace” keys)
  • .esc
  • .space
  • .up
  • .down
  • .left
  • .right

System modifier key

  • .ctrl
  • .alt
  • .shift
  • .meta

Mouse button modifier

  • .left
  • .right
  • .middle

34 Vue template compilation principles

The Vue compilation process is to convert the template to the render function in three steps

The first step is to convert the template string to Element ASTs. The second step is to do static node markup on the AST, which is mainly used for rendering optimization of the virtual DOM (optimizer). The third step is to use element ASTs to generate the render function code string (code generator).Copy the code

The relevant code is as follows

export function compileToFunctions(template) {
  // We need to turn the HTML string into the render function
  // 1. Convert HTML code into an AST syntax tree. The AST is used to describe the code itself, forming a tree structure that describes not only HTML but also CSS and JS syntax
  // Many libraries use ast, such as Webpack, Babel, esLint, etc
  let ast = parse(template);
  // 2. Optimize static nodes
  // This interested can see the source code does not affect the core function is not implemented
  // if (options.optimize ! == false) {
  // optimize(ast, options);
  / /}

  // 3. Regenerate the code from the AST
  // Our final generated code needs to be the same as the render function
  / / similar _c (' div '{id: "app"}, _c (' div', undefined, _v (" hello "+ _s (name)), _c (' span, undefined, _v (" world"))))
  // _c for create element, _v for create text, _s for text json. stringify-- parses the object into text
  let code = generate(ast);
  // Use the call to render to change the value of the variable in this convenience code
  let renderFn = new Function(`with(this){return ${code}} `);
  return renderFn;
}
Copy the code

Template compiling principle detail portal

How is the lifecycle hook implemented

The core implementation of Vue’s lifecycle hook implementation is to subscribe to all the lifecycle hooks passed in by the user (stored as an array) and then execute the corresponding hook method (publish) at once during the creation of the component instance.

The relevant code is as follows

export function callHook(vm, hook) {
  // Execute the lifecycle methods in turn
  const handlers = vm.$options[hook];
  if (handlers) {
    for (let i = 0; i < handlers.length; i++) {
      handlers[i].call(vm); // This in the lifecycle refers to the current instance}}}// When called
Vue.prototype._init = function (options) {
  const vm = this;
  vm.$options = mergeOptions(vm.constructor.options, options);
  callHook(vm, "beforeCreate"); // Before initializing the data
  // Initialize the state
  initState(vm);
  callHook(vm, "created"); // After initializing the data
  if(vm.$options.el) { vm.$mount(vm.$options.el); }};Copy the code

Life cycle implementation detail portal

36 Application scenarios and Principles of functional Components

The difference between functional components and ordinary components

1. Functional components need to specify functional:true 2 when declaring the component. There is no need to instantiate, so there is no this. This is replaced by the second argument to the render function, context. There is no lifecycle hook function, no calculated properties can be used, watch 4. You can't expose events from the $emit, and only call events from the context.listeners. Click method 5. Because functional components are not instantiated, an external reference to a component through a REF is actually a reference to HTMLElement 6. A functional component can use props as props, so all properties that are not declared in props are automatically resolved to prop. All undeclared properties of a functional component are resolved to $attrs and automatically mounted to the component root (which can be disabled by using the inheritAttrs attribute).Copy the code

Advantages 1. Because functional components do not need to be instantiated, are stateless, and have no life cycle, rendering performance is better than normal component 2. The functional component structure is simpler and the code structure is clearer

Usage scenario:

A simple presentation component used as a container component such as router-View is a functional component

“High-level component” – used to take a component as a parameter and return a wrapped component

The relevant code is as follows

if (isTrue(Ctor.options.functional)) {
  // A functional component is a functional component
  return createFunctionalComponent(Ctor, propsData, data, context, children);
}
const listeners = data.on;
data.on = data.nativeOn;
installComponentHooks(data); // Install the component-specific hook (functional components do not call this method and thus perform better than normal components)
Copy the code

37 Can you explain the principle of the routing mode commonly used in vue-Router

Hash pattern

  1. The value of location.hash is actually what follows the # in the URL. The feature is that while the hash appears in the URL, it is not included in the HTTP request and has no effect at all on the back end, so changing the hash will not reload the page.

  2. You can add listening events for hash changes

window.addEventListener("hashchange", funcRef, false);
Copy the code

Every time you change the hash (window.location.hash), a record is added to the browser’s access history. Using the above hash features, you can implement the “update view without re-requesting page” function of the front-end route

Features: Good compatibility but not beautiful

The history mode

Take advantage of the new pushState() and replaceState() methods in the HTML5 History Interface.

These two methods apply to the browser’s history station and provide the ability to modify the history on top of the existing back, Forward, and go. These two methods have one thing in common: when they are called to modify the browser history stack, the browser does not refresh the page even though the current URL has changed, which provides the basis for a single-page application front end route “update the view but do not re-request the page.”

Features: Although beautiful, refresh will appear 404 needs to be configured on the back end

38 Diff algorithm

It is recommended to see diff algorithm in detail for portal

Series of links (will be updated later)

  • Handwriting Vue2.0 source code (a) – response data principle
  • Handwriting Vue2.0 source code (2) – template compilation principle
  • Handwriting Vue2.0 source code (three) – initial rendering principle
  • Handwriting Vue2.0 source code (four) – rendering update principle
  • Handwriting Vue2.0 source code (five) – asynchronous update principle
  • Handwriting Vue2.0 source code (six) -diff algorithm principle
  • Handwriting Vue2.0 source code (seven) -Mixin Mixin principle
  • Handwriting Vue2.0 source code (eight) – component principle
  • Handwriting Vue2.0 source code (nine) – listening attribute principle
  • Handwriting Vue2.0 source code (ten) – the principle of computing attributes
  • Handwriting Vue2.0 source code (eleven) – global API principle
  • The most complete Vue interview questions + detailed answers
  • Handwritten vue-Router source code
  • Write vuex source code
  • Handwriting vue3.0 source code

Shark brother front touch fish technology group

Welcome technical exchanges within the fish can be pushed for help – link