What is the difference between the computed property computer and the common property Method in VUE?

Computed attribute is a vUE computing attribute, which is a data transformation mapping from the data layer to the view layer. Calculated properties are cached based on their dependencies, and are reevaluated only if the dependencies change. That is, as long as the dependencies have not changed, the calculated properties will immediately return the computed results on each access and no function will be executed.

Computed is responsive, whereas methods is not.

Call methods are different. Members defined by computed data are accessed like attributes. Members defined by methods must call computed in the form of functions with caching.

A member in computed can define only one function as a read-only attribute, or a member in methods can define get/set as a read-write attribute

Computed data does not support asynchron. If there is asynchronous operation in computed data, it is invalid and data changes cannot be monitored. If the declared computed property is very computated, and the number of visits is very large, the change time is very small, then computed data is needed. Caching saves us a lot of computation.

How does vUE’s bidirectional binding work?

Vue. js adopts data hijacking combined with publiser-subscriber mode. It hijabs (monitors) the setter and getter of each attribute through object-defineProperty () method provided by ES5, releases messages to subscribers when data changes, and triggers corresponding listening callback. And because synchronization is triggered on different data, changes can be sent precisely to the bound view, rather than checking all data at once.

Specific steps:

  1. You need the observer to recursively traverse the data objects, including the attributes of the child property objects, with getters and setters so that if you assign a value to that object, the setter will be triggered, and you’ll be listening for changes in the data
  2. Compile parses the template instructions, replaces variables in the template with data, initializes the render page view, and binds the corresponding node of each instruction to update function, adds subscribers to listen to the data, receives notification once the data changes, and updates the view
  3. Watcher subscribers serve as a bridge between the Observer and Compile. They do the following:
    • Add yourself to the attribute subscriber (DEP) during self instantiation
    • There must be an update() method itself
    • If you can call your own update() method and trigger the callback that is bound with compile, you are done
  4. MVVM, as a data binding entry, integrates observer, Compile and Watcher, monitors its model data changes through observer, and compiles template instructions through compile. Finally, the communication bridge between the Observer built by Watcher and COMPILE is used to achieve data changes – attempt to update; View interactive Changes (INPUT)–> Bidirectional binding effect of data model changes

Version comparison: VUE is bidirectional binding based on dependency collection; Version 3.0 before using Object. DefinePropetry, 3.0 the new use Proxy

  1. The advantages of bidirectional binding based on data hijacking/dependency collection do not require the display call. Vue uses data hijacking + publish and subscribe to directly notify the change and drive the view to get the exact change data directly. It hijacks the property setter, when the property value changes, we can accurately obtain the changed content newValue. No additional diff operations are required
  2. Disadvantages of Object.defineProperty.
    • Cannot listen on arrays: arrays have no getters and setters.
    • Because the array size is uncertain, if it’s too long it’s too much of a performance burden and you can only listen for properties, not the whole object, you have to iterate over properties and you can only listen for property changes, you can’t listen for property deletions
  3. The benefits of the proxy
    • You can listen to arrays
    • Listening on the entire object is not a property
    • 13 ways to intercept, much more powerful
    • It is more immutable to return a new object rather than modify the original;
  4. The disadvantage of the proxy
    • Poor compatibility and can not be smoothed by polyfill;

What is the principle of vue-Router?

How it works: Vue-Router updates the view without re-requesting the page

Vue-router can be set to three modes using the mode parameter:

Hash mode History mode Abstract mode.Copy the code
  1. Hash mode The default hash mode is based on the browser history API, using window.addeventListener (‘hashchange’,callback,false) to listen for the browser address. When push is called, the new route is added to the top of the stack of browser access history. When using replace, replace the top of the stack route from the browser’s access history with the value of the new route hash equal to the # and subsequent content in the URL. The browser loads the page into the DOM location based on the hash value. Anchor changes are only the behavior of the browser. Each anchor change still leaves a history in the browser, which can be returned to the previous position through the browser’s back button

  2. History History mode, based on the browser History API, using window. onpopState to listen for the browser address. Encapsulate pushState() and replaceState() in the browser’s history API, and modify the browser’s history stack when the method is called. So as to realize the URL jump without loading the page, but its problem is that when refreshing the page, it will go to the back-end route, so it needs the assistance of the server to avoid the URL cannot match the resource can return to the page

  3. Abstract does not involve records related to browser addresses. The process, like the Hash pattern, is used on the server side by maintaining an array that emulates the browser’s history stack. Use a browser history virtual admin background that is independent of the browser

Both hash and history modes listen for hashchange and popState routing via window.adDevevtListEnter (). You can use the back, Foward, and Go methods to access the browser’s history stack for various jumps. The Abstract pattern maintains an array of mock browser history stacks.

What is the difference between the computed property computer and the common property Method in VUE?

Computed attribute is a vUE computing attribute, which is a data transformation mapping from the data layer to the view layer. Calculated properties are cached based on their dependencies, and are reevaluated only if the dependencies change. That is, as long as the dependencies have not changed, the calculated properties will immediately return the computed results on each access and no function will be executed.

  • Computed is responsive, whereas methods is not.
  • Call methods are different. Members defined by computed data are accessed like attributes. Members defined by methods must call computed in the form of functions with caching.
  • A member in computed can define only one function as a read-only attribute, or a member in methods can define get/set as a read-write attribute
  • Computed does not support asynchrism, and it does not work when there is asynchronous operation in computed, so you cannot listen for changes in data

If you declare a computed property that has a lot of computations, a lot of visits, but little time to change, you need computed; Caching saves us a lot of computation.

How is keep-alive implemented in Vue? What is cached?

Keep-alive props include string or regular expression. Only components whose names match will be matched with exclude string or regular expression. Any component with a matching name will not be cached with a Max number. Maximum number of component instances can be cached

When keep-alive wraps dynamic components, inactive component instances are cached

The main process

  1. If the component name is not included in include or exclude and vNode is returned directly, the component is not cached
  2. Get the component instance key, if by getting the instance key, otherwise regenerate.
  3. The key generation rule, cid+”::”+tag, is not sufficient because the same constructor can be registered with different local components
  4. If the cache object exists, the component instance is directly fetched from the cache object to vNode. If it does not exist, the component instance is added to the cache object
  5. Maximum number of caches, when the number of caches exceeds the Max value, clear the first component in the keys array

Keep – the realization of the alive

Export default{name:'keep-alive', abstract:true,// an abstract component that does not render a DOM element by itself and does not appear in the parent component props: {include:patternTypes,// matching components, cache exclude:patternTypes,// not matching components, you cache Max :[String,Number],// Caching the maximum Number of instances of the component, Because the component instances (VNodes) are cached, too many will take up too much memory. }, create(){this.cache= object.create (null) this.keys=[]}, Destroyed (){for(const key in this.cache){pruneCacheEntry(this.cache,key,this.keys)}}, Mounted (){// Monitor include and exclude changes. This.$watch('include',(val)=>{pruneCache(this,(name=>matches(val,name))}) this.$watch('exclude',(val)=>{ pruneCache(this,(name)=>! matches(val,name)) }) }, }Copy the code

Render function

  1. It writes its own content inside the keep-alive component, so it can fetch the content of the default slot and fetch the component based on that
  2. Keep-alive is only valid for the first component, so get the first child
  3. Keep-alive is usually paired with dynamic components and route-views
function getFirstComponentChild(children:? Array<VNode>):? VNode{ if(Array.isArray(children)){ for(var i=0; i< children.length; i++){ const c=children[i] if(isDef(c)&&isDef(c.componentOptions)||isAsyncPlaceholder(c)){ return c } } } const Slot =this.$slots.default// Get the default slot const vNode: vNode =getFirstComponentChild(slot)// Get the first component const ComponentOptions :?VNodeComponentOptions=vnode &&vnode.componentOptions if(componentOptions){// Whether there is a component parameter const Name :? String =getComponentName(componentOptions) const {include,exclude}=this if(//not include (include && (! name || ! Matches (include, name))) | | / / excluded (exclude && name && matches (exclude, name))) {/ / if you don't match the name of the current component and include and exclude Return vnode} const {cache,keys}=this const key:? string=vnode.key == null? componentOptions.Ctor.cid + (componentOptions.tag ? ` : : ${componentOptions. Tag} ` : ') : vnode. Key if (cache [key]) {/ / LRU caching policy execution Vnode.componentinstance =cache[key]. ComponentInstance = undefined (keys,key) Key.push (key)}else{// If there is no key in the cache list, add it to the list, and check whether the range set by Max is exceeded. [key]=vnode keys.push(key) if(this.max && keys.length >parseInt(this.max)){ PruneCacheEntry (cache,key[0],keys,this. _vNode)}} // Set the keepAlive property of the component to true Vnode. Data. KeepAlive = true / / judge whether to execute component created, mounted lifecycle function}} return vnode | | (slot && slot [0])}Copy the code

Keep-alive caches vNode instances of all components through the cache array. When an existing component in the cache is in use, the component key is removed from the keys array, and then pushed to the end of the keys array to remove the least frequently used components

Step to summarize

  1. Get the instance object of the first child of keep-Alive to get the name of the component
  2. Use the current component name to match the original include and exclude to determine whether the current component needs caching. If no caching is required, the vNode instance of the current component is directly returned
  3. If it exists, remove the key from its original position and place the component’s key at the back of the array
  4. If not, place the component key in the array and determine if the current array of keys exceeds the range set by Max. If so, reduce the key value of the component that has not been used for the longest time
  5. Finally, set this component’s keepAlive to true

Keep-alive itself creation process and patch process cache rendering, Created and Mounted hook functions will not be executed based on vnode.componentInstance(undefined) and keepAlive properties. Instead, patch the cached component: directly insert the cached DOM object into the target element, completing the rendering process in the case of data update

First render the first render of a component: the DOM is mounted to the parent component to determine the abstract property of the component

const options=vm.$options let parent=options.parent if(parent && ! Options. abstract){// Determine the abstract property of the component, DOM while(parent.$options.abstract && parent.$parent){parent=parent.$parent} parent. vm.$parent=parent vm.$root=parent? parent:$root:vm vm.$children=[] vm.$refs={} vm._watcher=null vm._inactive=null vm._directInactive=false vm._isMounted=false vm._isDestroyed=false vm._isBeingDestoryed=false }Copy the code

Check whether keepAlive and componentInstance exist to determine whether to perform component perpatch or create componentInstance

if(vnode.componentInstance && ! __isDestroyed &&vnode.data.keepalive){// Render vnode.ponentInstance as undefined const MounteNode: any = vnode componentVNodeHooks. Prepatch (mountedNode mountedNode) / / prepatch function performs is a process of component update} else {const child=vnode.componentInstance=createComponentInstanceForVnode(vnode,activeInstance) } child.$mount(hydrating?vode.elm:undefined,hydrating) }Copy the code

The prepatch operation does not execute component mounted and created declaration cycles, but inserts the DOM directly

LRU(least recently Used) Cache policy LRU cache policy: Finds out the most recently used data from the memory and replaces it with new data. The LRU(least recently Used) algorithm weeds out data based on historical data access records. Its core idea is as follows: If the data has been accessed recently, there is a higher chance that it will be accessed in the future. The most common implementation is to use a linked list to store cached data. The detailed algorithm implementation is as follows

  1. New data is inserted into the linked list header
  2. Whenever cached data is accessed, it is moved to the head of the linked list
  3. When the list is full, discard the data at the end of the list

What are your methods for optimizing Vue projects?

  1. Optimization at the code level
    1. V-if and V-show are used in different scenarios
    2. Computed and Watch distinguish usage scenarios
    3. V-for traversal must add a key to the item and avoid using v-if at the same time
    4. Long list performance optimization
    5. Destruction of events
    6. Lazy loading of image resources
    7. Route lazy loading
    8. The introduction of third-party plug-ins on demand
    9. Optimize infinite list performance
    10. Server render SSR or prerender
  2. Optimization at the Webpack level
    • Webpack compresses images
    • Reduce redundant code from ES6 to ES5
    • Extract common code
    • Template precompilation
    • Extract the COMPONENT’s CSS
    • Optimize SourceMap
    • Build results output analysis
    • Compilation optimization of Vue project
  3. Optimization of basic Web technologies
    • Enable Gzip compression
    • Browser cache
    • The use of CDN
    • Use Chrome Performance to find Performance bottlenecks

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

Because components are used to reuse, and JS object reference relationship, if the data is an object in the component, then such scope without isolation, data attribute values of child components will influence each other, data option if the component is a function, then each instance can maintain an independent copy of the object being returned, Data property values between component instances do not affect each other; The instance of new Vue is not reused, so there is no object reference problem.

Can Vue detect a change when it assigns a value directly to an array item?

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

When you set an item directly using an index, e.g. Vm. items[indexOfItem] = newValue When you change the length of an array, e.g. Vm. items. Length = newLength To solve the first problem, Vue provides the following operations:

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

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

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

How can Vue components communicate with each other?

Communication between Vue components refers to only the following three types of communication:

  • Parent-child component communication
  • Intergenerational component communication
  • Sibling communication

Here’s a look at each:

  1. The method for props / $emit to communicate with parent and child components is the basis for Vue components, so I will not give an example here.
  2. Ref and parent/parent /parent /children are used for parent-child component communication

Ref: If used on a normal DOM element, the reference refers to the DOM element; If used on a child component, the reference refers to the component instance

The parent/parent/parent/children: visit the parent/child instance

  1. EventBus(emit/emit/emit/on) is an empty Vue instance that acts as the central EventBus(event center). It triggers events and listens for events to communicate with any component, including parent, sibling, or sibling components.
  2. Attrs/attrs/attrs/listeners applies to every generation component

Attrs: Contains feature bindings (except class and style) in parent scopes that are not recognized (and retrieved) by prop. When a component does not declare any prop, it contains all bindings in the parent scope (except class and style), and v−bind=”attrs: contains feature bindings (except class and style) in the parent scope that are not recognized (and retrieved) by prop. When a component does not declare any prop, it contains all bindings in the parent scope (except class and style), and contains feature bindings (except class and style) in the parent scope that are not recognized (and retrieved) by prop by v-bind=”attrs: “. When a component does not declare any prop, all parent-scoped bindings (except class and style) are included, and the internal component can be passed in via v−bind=”attrs”. Often used in conjunction with the inheritAttrs option. Listeners: contain V −on event listeners in the parent scope (native modifiers are not included). Listeners can notice the process by means of V −on=” Listeners: V-ON event listeners in the parent scope (without the.native modifier). The listeners can be listeners of V-on events in the parent scope (native modifiers are not included) via V-on =”listeners: Internal components can be passed on via V − ON =” Listeners”

  1. Provide/Inject This function is applicable to provide/inject variables in descendant components through Provider and inject variables in descendant components. Provide/Inject API mainly solves the communication problem between cross-level components, but its usage scenario is mainly that sub-components obtain the state of the upper level components, and a relationship between active provision and dependency injection is established between cross-level components.
  2. Vuex is suitable for parent-child, intergenerational, and sibling component communication. Vuex is a state management mode developed specifically for vue.js applications. At the heart of every Vuex application is the Store. A “store” is basically a container that contains most of the states in your app.

Vuex’s state storage is reactive. When the Vue component reads the state from the Store, if the state in the store changes, the corresponding component is updated efficiently accordingly. The only way to change the state in a store is to commit mutation explicitly. This allows us to easily track each state change.

What about Vue’s parent and child lifecycle hook function execution order?

Vue’s parent and child component lifecycle hook function execution sequence can be categorized into the following four parts:

  • Loading the rendering process

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

  • 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

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

Vue.js is a framework for building client applications. By default, the Vue component can be exported to the browser for DOM generation and DOM manipulation. However, it is also possible to render the same component as server-side HTML strings, send them directly to the browser, and finally “activate” these static tags into a fully interactive application on the client side. That is, SSR roughly means that vUE renders the entire HTML fragment of the label 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.

Advantages and disadvantages of server rendering SSR are as follows:

  1. Advantages of server-side rendering:
  • Better SEO: Because the content of SPA page is obtained through Ajax, and the search engine crawl tool does not wait for the completion of Ajax asynchronism before grabbing the page content, so the content of SPA page obtained through Ajax cannot be captured; SSR is returned directly from the server to the rendered page (the data is already included in the page), so the search engine crawler can grab the rendered page
  • Faster content arrival time (faster loading on the first screen) : SPA will wait for all Vue compiled JS files to be downloaded before rendering the page. File download takes a certain amount of time, so rendering on the first screen takes a certain amount of time. SSR directly returns the page rendered by the server directly, without waiting to download JS files and render again, so SSR has a faster content arrival time
  1. Disadvantages of server-side rendering:
  • More development constraints: for example, server-side rendering only supports the beforCreate and Created hook functions, resulting in some external extension libraries requiring special handling to run in server-side rendering applications; And unlike fully static single-page application SPA, which can be deployed on any static file server, server-side rendering applications need to be in the Node.js server running environment;
  • More server load: Rendering a full application in Node.js is obviously more CPU-intensive than a server that only serves static files, so if you expect to use it in a high traffic environment, Prepare your server load and use caching strategies wisely.

What about Vue’s $nextTick principle?

Js execution mechanism (Event Loop)

Js execution is single threaded and is based on event loops

All synchronization tasks are executed on the main thread, forming an execution stack. Outside the main thread, there is a task queue, and whenever the asynchronous task has a result, an event is placed in the task queue. When all synchronization tasks in the execution stack are completed, the task queue is read. The corresponding asynchronous task will end the wait state and enter the execution stack. The main thread repeats step 3, where thread execution is a tick, and all asynchronous results are scheduled through the task queue. Event Loop is divided into macro task and micro task. No matter the macro task or micro task is executed, it will enter the next tick and process UI rendering between the two ticks. Since Vue DOM update is performed asynchronously, that is, when data is modified, the view will not update immediately but monitor data changes. And cached in the same event cycle, such as the completion of all data changes in the same data cycle, in the same view update. To ensure that you get the updated DOM, the vue.nexttick () method is set

What is one of the core methods of $nextTick Vue is explained in the official documentation as follows: a delayed callback that is executed after the next DOM update cycle. Use this method immediately after modifying the data to get the updated DOM

  1. MutationObserver

MutationObserver is an API in HTML5. It is an interface for listening for DOM changes. It can listen for child node deletion, attribute modification, text content modification on a DOM object, etc. The calling procedure first binds a callback to the MO instance object, which is triggered when changes are heard on the MO instance object. The MO callbacks here are performed in MicroTask

Const Observer=new MutationObserver(callback); Const textNode=" Hello world!" Observer.observe(textNode,{characterData:true}) observer. observe(textNode,{characterData:true})Copy the code
  1. Source code analysis

The implementation of nextTick has a separate JS file to maintain it. The nextTick source code is mainly divided into two parts: capability detection and the different ways of executing callback queue capability detection. Since the macro task takes more time than the micro task, the micro task is preferred when the browser supports it. If the browser does not support microtasks, use macro tasks

Import {noop} from './util'; Import {handleError} from './error'; Import {isIE,isIOS,isNative} from './env'; Const callbacks=[]; const callbacks=[]; // Whether a callback function is being executed const flag=false; Function shift(){flag=false; function shift(){flag=false; $nextTick ($nextTick, $nextTick, $nextTick, $nextTick, $nextTick, $nextTick, $nextTick, $nextTick) Const cb=callbacks. Slice (0) callbacks. Length =0 for(var I =0; i<cb.length; i++){ cb[i]() } } const timeFunc; FlushCallbacks if(typeof Promise! == "undefined" && isNative(Promise)){ const p=Promise.resolve() timeFunc=()=>{ p.then(flushCallbacks); // The IOS UIView, peomise.then callbacks are pushed to the microTask queue, but the queue may not execute as expected // therefore, Add an empty timer force microTask if (isIOS) setTimeout(noop)} isUsingMicroTask=true; }else if(! isIE && typeof MutationObserver ! =='undefined' && (isNative(MutationObserver) || MutationObserver.toString === "[Object MutationObserverConstructor]")){ // When the native Promise is not available, use the native MutationObserver let counter=1 FlushCallbacks const obs=new MutationObserver(flushCallbacks); Const textNode=document.createTextNode(String(conter)) obs. Observe (textNode,{characterData:true,// Monitor target change}) // Each time timeFunc is executed, hi switches the contents of the text node between 0 and 1. TimeFunc =()=>{counter=(counter+1)%2 textNode.data=String(counter)// Trigger the callback function} isUsingMicroTask=true; }else if(typeof setImmediate ! == 'undefined' && isNative(setImmediate)){ timeFunc=()=>{ setImmediate(flushCallbacks) } }else{ timeFunc=()=>{ setTimeout(flushCallbacks,0) } }Copy the code

Deferred call priorities are as follows: Promise > MutationObserver > setImmediate > setTimeout

export function nextTick(cd? Callbacks. Push (()=>{if(cb){try{cb.call(CTX)}catch(e){if(cb){if(cb){cb.call(CTX)}catch(e){ HandleError (e, CTX,'nextTick')}}else if(_resolve){_resolve(CTX)}}) // if flag is false, timeFunc if(! flag){ flag=true; TimeFunc ()} // When no cb argument is passed, provide a promise-like call such as nextTick().then(()=>{}). _resolve jumps to if(! cd && typeof Promise ! == 'undefined'){ return new Promise(resolve=>{ _resolve=resolve }) } }Copy the code

NextTick. Js exposes the nextTick parameter, so vue. nextTick is executed each time it is called:

  • Press the incoming callback cb into the Callbacks array
  • Execute the timeFunc function and defer calling the flushCallbacks function
  • The traversal execution callbacks array has functions in it
  • The reason why callbacks do not execute callbacks directly on nextTick is to ensure that multiple nextticks are executed on the same tick, so that they do not start multiple asynchronous tasks. Instead, the asynchronous tasks are folded into one synchronous task and the nextTick is executed.
NextTick ([callback,context]) {Function}[callback]: a callback Function, which provides a promise to call {Object}[context]: the context in which the callback Function is executed, is automatically bound to the instance in which it is called by defaultCopy the code
// Change data vm. Message ="changed"; // If you want to use the updated DOM immediately, it doesn't work because the DOM hasn't updated console.log(vm.$el.textContent) after setting message. NextTick (function(){//DOM update, "Changed" console.log(vm.$el.textContent)}) // used as a promise, NextTick ().then(function(){//DOM update code})Copy the code

The Vue instance method vm.$nextTick is further encapsulated by setting the context parameter to the current Vue instance. Vue.nexttick () is used to retrieve the updated DOM. Trigger timing: The Vue. NextTick () callback is executed immediately after the DOM is updated after the data in the same event loop changes

The code in the same event loop completes — DOM updates — and nextTick Callback fires

Application scenarios

  • DOM operations performed by the Created () hook function in the Vue lifecycle must be placed in the vue.nexttick () callback because the DOM is not actually rendering when the Created () hook function is executed.

  • An operation to be performed after data changes that requires the use of a DOM structure that changes as data changes should be placed in the vue.nexttick () callback function for the following reasons: The Vue performs DOM updates asynchronously. Whenever a data change is observed, the Vue opens a queue and buffers all data changes that occur in the same event loop. If the same Watcher is triggered more than once, the Vue will only be pushed into the queue once

conclusion

  • Vue’s nextTick is essentially an application of EventLoop, the JS execution principle

Core applications of nextTick: The native JS methods of Promise, MutationObserver, setImmediate and setTimeout simulate the implementation of corresponding micro/macro tasks, essentially in order to use the ASYNCHRONOUS callback task queue of JS to achieve their own asynchronous callback queue in Vue framework

  • NextTick is not only a call method for asynchronous queues within Vue, but also allows developers to use this method in real projects for subsequent logical processing of DOM data updates in real applications

NextTick is a typical example of applying underlying JS execution principles to a specific case

The reason for introducing the asynchronous update queue mechanism

If the update is synchronous, assigning one or more attributes multiple times triggers frequent UI/DOM rendering, which reduces unnecessary rendering

At the same time, due to the introduction of VirtualDOM, each time the state changes, the state change signal will be sent to the component, the component internal use VirtualDOM to calculate the need to update the specific DOM node, and then the DOM update operation, each time the state update after the rendering process needs more calculation, This wasted effort also wastes more performance, so asynchronous rendering becomes more critical.

How is v-Model implemented and what is syntactic sugar actually?

Syntactic sugar is a syntax added to a computer language that has no effect on the language’s functionality but is more convenient for programmers to use. In general, using syntactic sugar increases the readability of programs and thus reduces the chance of errors in program code. Sugar achieves runtime equivalence without changing the syntactic structure of its location. The code before and after sugar compiles the same, but the code is cleaner, smoother and more semantically natural

Realize the principle of

  1. Applies to normal form elements

The value bound to the input dynamically points to the message variable and dynamically sets message to the target value when the input event is triggered

<input V-model ="something"/> // equivalent to <input v-bind:value="message" V-on :input="message=$event.target.value"/> $event. Target: dom of the event object //$event. Target: dom of the event object //$event. // In :value, something-->valueCopy the code
  1. Acts on components

In custom components, the V-Model defaults to a prop named Value and an event named input

<child :value=”text” @input=”function(e){text=e}”> <child :value=”text” @input=”function(e){text=e}”> The V-Model property can be used to configure the prop property received by the child component and the event name dispatched

<parent-input v-model="parent"></parent-input> equivalent to <parent-input v-bind:value="parent" V-on :input="parent=$event.target.value"></parent-input> <input v-bind: input=" message" V-on :input="onmessage"/> props:{value:message} methods:{ onmessage(e){ $emit('input',e.target.value) } }Copy the code

By default, a V-Model on a component will use value as a prop and input as an event, but some input types such as checkboxes and checkbox buttons may want to use Value Prop for different purposes. Using the Model option sidesteps the conflict of this situation. Js listens for changes in the input field, using the onInput event, which will be triggered immediately after the data changes. Emit the data via the input event and receive it in the parent component. The parent component sets the value of v−model to inputemit out, which is received in the parent component. The parent component sets the value of the V-model to inputemit out, which the parent component receives. The parent sets the value of v−model to the value obtained by Inputemit.

Can a child component directly change the parent component’s data? What’s your reason?

The main purpose is to maintain one-way data flow between parent and child components

Every time the parent component is updated, all prop in the child component will be refreshed to the latest value

If you do, Vue will issue a warning in the browser console

Vue advocates one-way data flow, where updates to the parent props flow to the child components, but not the other way around. This is to prevent unexpected changes in the state of the parent component, making the application data flow difficult to understand, resulting in data flow chaos. If the one-way data stream is broken, debug can be very costly when applying complex situations

Only a custom event is sent via $emit, which is then modified by the parent.

Can you explain the hash and history routing modes used in vue-router?

  1. Implementation principles of the Hash mode

Early implementations of front-end routing were based on location.hash. The principle is simple: the value of location.hash is what comes after the # in the URL. For example, here’s a website whose location.hash value is ‘#search’ :

The implementation of www.word.com#search Hash routing pattern 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 made to the server, the hash part will not be sent. Changes to the hash value add a record to the browser’s access history. So we can switch the hash using the browser’s back and forward buttons. You can use the a tag and set the href attribute. When the user clicks on the tag, the HASH value of the URL will change. Or use JavaScript to assign loaction.hash to change the HASH value of the URL. We can use the hashchange event to listen for changes in the hash value to jump (render) the page. The two main apis are history.pushstate () and history.replacestate (). Both apis allow you to manipulate the browser’s history without refreshing it. The only difference is that the former is to add a history, while the latter is to replace the current history directly, as shown below:

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

The history routing pattern is implemented based on the following features:

PushState and repalceState are apis to implement URL changes and we can use the popState event to listen for URL changes, History.pushstate () or history.replacEstate () will not trigger the popState event, so we need to manually trigger the page jump (render).Copy the code

Talk about the Vue lifecycle and what it does in each phase

BeforeCreate (created before) data observation and initialization events have not started

Created completes data observation, property and method operations, initialization events, and the $EL property is not yet displayed

BeforeMounted is called before the mount begins, and the associated render function is called for the first time. The example completes the following configuration: compile the template, and generate HTML from the data and template inside the data. The HTML has not been mounted to the page yet

Mounted after el is replaced by a newly created vm.$el and mounted to the instance. The example has completed the configuration of replacing the DOM object pointed to by the EL attribute with the HTML content compiled above. Finish rendering the HTML from the template to an HTML page, enabling Ajax interaction

BeforeUpdate is called before data is updated and occurs before the virtual DOM is re-rendered and patched. You can change the state further in this hook without triggering a repeat rendering process

Update is called after the virtual DOM has been re-rendered and patched due to data changes. When called, the component DOM is already updated, so dom-dependent operations can be performed. However, in most cases, avoid changing the state during this period, as this may cause the update to fail to loop. This hook is not called during server-side rendering

BeforeDestroy called before instance destruction. The instance is still fully usable.

Called after the instance is destroyed. When called, all event listeners are removed and all subinstances are destroyed. This hook is not called during server-side rendering

Vue Template to Render

Process analysis

Vue templates are compiled as follows: template-ast-render function

Vue converts the template to the render function by executing compileToFunctions in the template compilation

Main cores for compileToFunctions:

  1. Call the parse method to convert template to an AST tree (abstract syntax tree)

The purpose of parse is to convert a template into an AST tree, which is a way to describe the entire template in the form of A JS object.

Parsing process: The template is parsed sequentially using regular expressions. When the start tag, close tag, and text are parsed, the corresponding callback functions are executed respectively to form the AST tree

There are three types of AST element nodes (type) : normal element –1, expression –2, and plain text –3

  1. Optimization of static nodes this process mainly analyzes which are static nodes, make a mark in it, for the later update rendering can be directly skipped, optimization of static nodes

Walk through the AST in depth to see if the node element of each subtree is a static node or a static node root. If they are static nodes, the DOM they generate never changes, which is optimized for runtime template updates

  1. Generate compiles the AST abstract syntax tree into a Render string, puts the static part into a staticRender, and finally generates the Render Function with new Function(render)

This section describes the navigation hook function in VUe-Router

  1. Global hook functions beforeEach and afterEach

BeforeEach has three parameters, to represents the route object to enter and from represents the route object to leave. Next is a mandatory function. If no arguments are passed, the next hook function is executed, terminating the jump if false, navigating to the corresponding route if a path is passed, and terminating navigation if error is passed, which passes an error listener

  1. Single route exclusive hook function beforeEnter, which is defined directly on route configuration

  2. There are three main navigation hooks in a component: beforeRouteEnter, beforeRouteUpdate, and beforeRouteLeave. They are defined directly within the routing component