Recently, I sorted out the high-frequency front end questions and shared them with you. If you have any questions, please point out!

Due to the word limit of a single article, the Vue article is divided into two parts. This is the next part.

Front end examination series of articles:

[1] “2021” a summary of the high-frequency front end of the HTML text

[2] “2021” CSS chapter

【3】 “2021” iS the most important part of the English language.

【4】 “2021” 高 速 中 考 试 内 容

[5] “2021” Vue chapter (1)

[6] “2021” Vue chapter (2)

【7】 React (2021)

【8】 React (2021)

[9] “2021” in computer Networks

[10] “2021” a summary of the browser principles

[11] “2021” high frequency front end test summary of performance optimization

[12] “2021” high frequency front end test summary handwritten code

[13] “2021” high frequency front end test summary code output results

Four, routing,

1. How to implement lazy loading of vue-Router

Non-lazy loading:

import List from '@/components/list.vue'
const router = new VueRouter({
  routes: [{path: '/list'.component: List }
  ]
})
Copy the code

(1) Scheme 1 (common) : use arrow function +import to load dynamically

const List = () = > import('@/components/list.vue')
const router = new VueRouter({
  routes: [{path: '/list'.component: List }
  ]
})
Copy the code

(2) Scheme 2: use arrow function +require dynamic loading

const router = new Router({
  routes: [{path: '/list'.component: resolve= > require(['@/components/list'], resolve)
   }
  ]
})
Copy the code

(3) Scheme 3: Webpack’s Require. ensure technology can also realize on-demand loading. In this case, multiple routes with the same chunkName are combined and packaged into a single JS file.

// r is resolve
const List = r= > require.ensure([], () = > r(require('@/components/list')), 'list');
// This is the official recommendation to write lazy load by module
const router = new Router({
  routes: [{path: '/list'.component: List,
    name: 'list'}]}))Copy the code

2. The difference between the hash and history modes of routes

Vue-router supports hash mode and history mode. The default routing mode is hash mode.

1. The hash pattern

Summary: Hash mode is the default mode in development. Its URL has a #, such as www.abc.com/#/vue, and its hash value is #/vue.

Features: Hash values appear in urls, but not HTTP requests, and have no impact on the back end. So changing the hash value does not reload the page. Browser support for this mode is good, and it is also supported by earlier versions of Internet Explorer. Hash routes are called front-end routes and have become standard configuration of SPA (single-page application).

Principle: The main principle of hash mode is the onHashchange () event:

window.onhashchange = function(event){
	console.log(event.oldURL, event.newURL);
	let hash = location.hash.slice(1);
}
Copy the code

The advantage of using the onHashChange () event is that when the hash value of the page changes, the Window can listen for the change and load the code according to the rules, without the need for a request from the back end. In addition, the URL corresponding to the hash change is recorded by the browser so that the browser can move the page forward and backward. Although the backend server is not requested, the hash value of the page is associated with the corresponding URL.

2. The history mode

Summary: The history mode does not have # in the URL. It uses the traditional route distribution mode, that is, when a user enters a URL, the server receives the request, parses the URL, and then performs the corresponding logical processing. Features: When using history mode, the URL looks like this: abc.com/user/id. It looks better than hash mode. However, history mode requires background configuration support. If the background is not configured correctly, 404 will be returned when accessed. The history API can be divided into two parts: switching the history state and modifying the history state:

  • Modifying history Status: includes new additions to the HTML5 History InterfacepushState()replaceState()Method, which are applied to the browser’s history stack and provide the ability to modify the history. It’s just that when they make a change, even though they change the URL, the browser doesn’t immediately send the request to the backend. If you want to change the URL without refreshing the page, you need both apis on the front end.
  • Switching history status:includingforward(),back(),go()Three methods, corresponding to the browser forward, back, jump operation.

Although history mode discarded the ugly #. However, it also has its own disadvantage, is that when the page is refreshed, if there is no corresponding route or resource, it will spawn 404.

If you want to switch to History mode, do the following (and the backend) :

const router = new VueRouter({
  mode: 'history'.routes: [...]. })Copy the code

3. Compare the two modes

Calling history.pushState() has the following advantages over modifying the hash directly:

  • PushState () sets the new URL to any URL of the same origin as the current URL; Hash can only change the part after #, so you can only set the URL of the same document as the current URL.
  • PushState () sets the new URL to be exactly the same as the current URL, which also adds the record to the stack; The new hash value must be different to trigger the action to add the record to the stack;
  • PushState () uses the stateObject argument to add any type of data to a record; Hash can only add short strings;
  • PushState () sets the title property in addition for later use.
  • In hash mode, only the URL before the hash symbol is included in the request. If the back end does not fully cover the route, no 404 error is returned. In history mode, the url of the front end must be the same as the URL of the request sent from the back end. If the route is not processed, a 404 error is returned.

Both hash mode and history mode have their own advantages and disadvantages, so use them selectively according to the actual situation.

3. How do I obtain the hash change of the page

$route = $route

// Listen when the route changes
watch: {
  $route: {
    handler: function(val, oldVal){
      console.log(val);
    },
    // Deep observation monitor
    deep: true}},Copy the code

The hash value of window.location.hash is readable and writable to determine whether the state has changed. The hash value can be read to add a history record without reloading the page.

4. $route and $routerThe difference between

  • $route is the “routing information object”, including path, Params, Hash, Query, fullPath, matched, name and other routing information parameters
  • $router is a “router instance” object that includes hop methods, hook functions, etc.

5. How do I define a dynamic route? How do I get the passed dynamic parameters?

(1) Param method

  • Configure the route format:/router/:id
  • How it is passed: Follow path with the corresponding value
  • The path formed after transmission:/router/123

1) Route definition

/ / in the APP. In vue
<router-link :to="'/user/'+userId"The replace > user < / router - the link >/ / in the index. Js
{
   path: '/user/:userid'.component: User,
},
Copy the code

2) Route jump

// Method 1:
<router-link :to="{ name: 'users', params: { uname: wade }}"> button < / router - the link// Method 2:
this.$router.push({name:'users'.params: {uname:wade}})

// Method 3:
this.$router.push('/user/' + wade)
Copy the code

$route.params.userid = $route.params.userid

(2) Query mode

  • Configure the route format:/router, that is, the common configuration
  • Pass method: The object uses the Query key as the pass method
  • The path formed after transmission:/route? id=123

1) Route definition

// Method 1: Create an object directly on the router-link tag
<router-link :to="{path:'/profile',query:{name:'why',age:28,height:188}}"> file < / router - the link >// Method 2: write the button as a click event
<button @click='profileClick'>my</button>    

profileClick(){
  this.$router.push({
    path: "/profile".query: {
        name: "kobi".age: "28".height: 198}}); }Copy the code

2) Jump method

// Method 1:
<router-link :to="{ name: 'users', query: { uname: james }}"> button < / router - the link >// Method 2:
this.$router.push({ name: 'users'.query: {uname:james }})

// Method 3:
<router-link :to="{ path: '/user', query: { uname:james }}"> button < / router - the link >// Method 4:
this.$router.push({ path: '/user'.query: {uname:james }})

// Method 5:
this.$router.push('/user? uname=' + jsmes)
Copy the code

3) Get parameters

Get the passed value with $route.queryCopy the code

6. Vue-router Indicates the life cycle of the router hook

Vue-Router navigation guard

Sometimes, some operations need to be performed through routing, such as the most common login permission verification. When the user meets the conditions, the user can enter the navigation. Otherwise, the user can cancel the jump and jump to the login page for login. There are many ways to implement routing navigation: global, single route proprietary, or component-level

  1. Global routing hook

Vue-router globally has three routing hooks;

  • Router. beforeEach Global front-guard before entering a route
  • Router.beforeresolve Global resolution guard (2.5.0+) is called after the beforeRouteEnter call
  • AfterEach Global post-hook after entering a route

Specific use:

  • BeforeEach (Determine whether you are logged in, jump to the login page if you are not logged in)
router.beforeEach((to, from, next) = > {  
    let ifInfo = Vue.prototype.$common.getSession('userData');  // Determine whether to log in to the storage information
    if(! ifInfo) {// sessionStorage does not store user information
        if (to.path == '/') { 
            // Next ()
            next();    
        } else { 
            // Otherwise jump to login
            Message.warning("Please log in again!");     
            window.location.href = Vue.prototype.$loginUrl; }}else {    
        returnnext(); }})Copy the code
  • AfterEach (Scroll bar returns to top after jump)
router.afterEach((to, from) = > {  
    // The scroll bar returns to the top after the jump
    window.scrollTo(0.0);
});
Copy the code
  1. A single route has exclusive hooks

BeforeEnter You can configure guards for certain routes individually if you do not want to configure guards globally. This parameter has three parameters: to, from, and next

export default[{path: '/'.name: 'login'.component: login,        
        beforeEnter: (to, from, next) = > {          
            console.log('Coming to login page')          
            next()        
        }    
    }
]
Copy the code
  1. Component internal hook

BeforeRouteUpdate, beforeRouteEnter, beforeRouteLeave

Each of these three hooks takes three parameters: to, from, and next

  • BeforeRouteEnter: triggered before entering a component
  • BeforeRouteUpdate: triggered when the current address changes and the rehash is reused. For example, the path foo/∶id with dynamic parameters jumps between /foo/1 and /foo/2. Since the same FOA component will be rendered, this hook will be called in this case
  • BeforeRouteLeave: Leave component called

Note that this is not yet accessible from within the beforeRouteEnter component, because the component instance has not been created before the guard executes. You need to pass a callback to Next to access this, for example:

beforeRouteEnter(to, from, next) {      
    next(target= > {        
        if (from.path == '/classProcess') {          
            target.isFromProcess = true}})}Copy the code

Vue routing hook in the life cycle function

  1. Complete routing navigation resolution flow (no other lifecycle)
  • Trigger to enter other routes.
  • Call the component guard beforeRouteLeave to leave the route
  • Call office front guard: beforeEach
  • Call beforeRouteUpdate in the reused component
  • Call the route exclusive guard beforeEnter.
  • Parse the asynchronous routing component.
  • Call beforeRouteEnter in the incoming routing component
  • Call the global resolution guard beforeResolve
  • Navigation confirmed.
  • Call the afterEach hook of the global post-hook.
  • DOM update (Mounted) is triggered.
  • Execute the callback passed to Next in the beforeRouteEnter guard
  1. The full order in which the hooks are triggered

A combination of routing navigation, keep-alive, and component lifecycle hooks triggers the sequence, assuming it leaves component A and enters component B for the first time:

  • BeforeRouteLeave: Hook of a routing component before it leaves the route.
  • BeforeEach: global front-guard of routes, used for login authentication and global route loading.
  • BeforeEnter: Exclusive route guard
  • BeforeRouteEnter: Pre-route hook for a component of a routing component.
  • BeforeResolve: global route resolution guard
  • AfterEach: Routes a global post-hook
  • BeforeCreate: component life cycle, cannot access tAis.
  • created; Component life cycle, which has access to tAis but not dom.
  • BeforeMount: Component life cycle
  • Deactivated: Deactivates the cache component A or triggers a’s beforeDestroy and Destroyed component destruction hooks.
  • Mounted: Accesses and manipulates the DOM.
  • Activated: Goes into the cache component, into a’s nested child component (if any).
  • Execute the beforeRouteEnter callback next.
  1. The navigation behavior is triggered to complete the navigation process
  • The navigation behavior is triggered and the navigation is not acknowledged.
  • Call the leave guard beforeRouteLeave in the deactivated component.
  • Call the global beforeEach guard.
  • Call the beforeRouteUpdate guard (2.2+) in the reused component.
  • Call beforeEnteY in routing configuration.
  • Resolve asynchronous routing components (if any).
  • Call beforeRouteEnter in the activated component.
  • Call the global beforeResolve guard (2.5+) to indicate that the parsing phase is complete.
  • Navigation confirmed.
  • Call the global afterEach hook.
  • For non-reusable components, start the life cycle of the component instance: beforeCreate&created, beforeMount&mounted
  • Trigger a DOM update.
  • Call the callback passed to Next in the beforeRouteEnter guard with the created instance.
  • Navigation to complete

7. What is the difference between vue-router jump and location.href

  • uselocation.href= /url To jump, simple and convenient, but refresh the page;
  • usehistory.pushState( /url ), no page refresh, static jump;
  • Import the Router and use itrouter.push( /url )To jump, useddiffThe algorithm realizes loading on demand and reduces the consumption of DOM. Actually use router to jump and usehistory.pushState()It doesn’t make any difference because vue-Router is used, righthistory.pushState(), especially in History mode.

8. Difference between Params and Query

Usage: Query is introduced with path, params is introduced with name, and the received parameters are similar: this.$route.query.name and this.$route.params.name.

Query is more like AJAX get, params is more like POST. The former displays parameters in the browser address bar, while the latter does not

Note: The query refresh does not lose the data in query. The params refresh does lose the data in params.

9. Vue-router what are the navigation guards

  • Global prefixes/hooks: beforeEach, beforeResolve, afterEach
  • Exclusive guard for routing: beforeEnter
  • Guards within components: beforeRouteEnter, beforeRouteUpdate, beforeRouteLeave

10. Understanding of front-end routing

In the early days of front-end technology, A URL corresponds to A page. If you want to switch from page A to page B, it is inevitable that the page is refreshed. It wasn’t a great experience, but at first it was a necessity — users could only request data again if they refreshed the page.

Then something changed — Ajax came along that allowed people to make requests without refreshing the page; Co-existing with this is the need to update the content of a page without refreshing it. In this context, SPA (single page application) emerged.

SPA greatly improves the user experience by allowing the page to update its content without refreshing it, making it smoother to switch between content. But in the early days of SPA, people didn’t think about “positioning” — the URL of the page was the same before and after the content switch, which caused two problems:

  • The SPA doesn’t really know “where we are” with the current page. You might “progress” repeatedly through a site before calling up a piece of content, but when you refresh the page, everything is zeroed out and you have to repeat what you did before you can reposition the content — SPA doesn’t “remember” what you did.
  • Having only one URL to map to a page is not SEO friendly either, and the search engine cannot gather comprehensive information

To solve this problem, front-end routing emerged.

Front-end routing helps us “remember” where the user is currently on a single page — matching each view in the SPA with a unique identity. This means that new content triggered by a user’s advance or retreat is mapped to a different URL. Even if he refreshes the page, the content will not be lost because the current URL identifies where he is.

So how do you do that? First, we need to solve two problems:

  • When the user refreshes the page, the browser by default relocates the resource (sends the request) based on the current URL. This action is not necessary for a SPA, because our SPA, as a single page, will have only one resource corresponding to it anyway. In this case, if the normal request-refresh process is followed, the user’s forward and backward operations cannot be recorded.
  • A single page application is a URL and a set of resources for the server. So how to use “different URLS” to map different view contents?

Judging from these two problems, the server can’t save this scenario at all. So rely on our front end self-reliance, otherwise how to call “front-end routing”? As a front end, it can provide the following solutions:

  • Intercepts user refresh operations to prevent the server from blindly responding and returning resource content that does not meet expectations. Digest the refresh completely in the front-end logic.
  • Aware of URL changes. This is not about reinventing urls and creating N urls out of thin air. Rather, the URL is still the same URL, but we can do some minor processing to it — these processing does not affect the NATURE of the URL itself, does not affect the server’s recognition of it, only our front-end perception. Once we sense that, we use JS to generate different content for it based on those changes.

Fifth, Vuex

1. The principle of Vuex

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 makes it easy to track changes in each state.

Vuex establishes a complete ecosystem for Vue Components, including API calls under development.(1) Main functions in the core process:

  • Vue Components are Vue Components that trigger events or Actions (Actions).
  • The action sent out in the component must want to obtain or change data, but in VUEX, data is centrally managed and data cannot be changed directly, so this action will be submitted to Mutations.
  • Then Mutations Mutate the data in State;
  • When the data in State is changed, it is re-rendered to the Vue Components, and the component displays the updated data to complete the process.

(2) Main functions of each module in the core process:

  • Vue Components: Vue component. On the HTML page, responsible for receiving user operations and other interactive behaviors, execute the Dispatch method to trigger corresponding actions to respond.
  • dispatch: Action action trigger method, is the only method that can execute action.
  • actions: Operation behavior processing module. Responsible for handling all interactions received by Vue Components. Contains synchronous/asynchronous operations and supports multiple methods of the same name that are triggered in the order of registration. Requests to the background API are made in this module, including triggering other actions and submitting mutations. This module provides the encapsulation of promises to support the chain firing of actions.
  • commit: State change submission operation method. Committing for mutation is the only way to perform mutation.
  • mutations: State change operation method. Is the only recommended method for Vuex to modify state. Other modification methods will report errors in strict mode. This method can only perform synchronous operations, and the method name must be globally unique. Some hooks will be exposed during the operation for state monitoring and so on.
  • state: page status management container object. Fragmented data of Vuecomponents data objects are centrally stored and globally unique for unified state management. The data required for page display is read from this object, leveraging Vue’s fine-grained data response mechanism for efficient status updates.
  • getters: state Object reading method. This module is not listed separately and should be included in Render, where Vue Components read the global state object.

2. Difference between Action and mutation in Vuex

The mutation operations are a series of synchronization functions that modify the state of a variable in state. When using VuEX, you need to commit the content that needs to be acted on. Mutation is very similar to events: each mutation has a string event type (type) and a callback function (handler). This callback is where the actual state change takes place, and it accepts state as the first argument:

const store = new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    increment (state) {
      state.count++      // Change the state}}})Copy the code

This function is called when a mutation of type INCREMENT is triggered:

store.commit('increment')
Copy the code

Action is similar to mutation, except that:

  • Actions can contain any asynchronous operation.
  • The Action commits mutation rather than a direct state change.
const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
    increment (context) {
      context.commit('increment')}}})Copy the code

The Action function accepts a context object with the same methods and properties as the store instance, so you can submit a mutation by calling context.mit. Or get state and getters via context.state and context.getters. So, the differences are as follows:

  • Mutation focuses on modifying State, which is theoretically the only way to modify State; Action Business code, asynchronous request.
  • Mutation: must be executed synchronously; Action: Can be asynchronous, but cannot operate State directly.
  • When a view is updated, actions are triggered, and mutations are triggered by actions
  • The mutation parameter is state, which contains the data in the store; The store argument is context, which is the parent of state and contains state and getters

3. Differences between Vuex and localStorage

(1) The most important difference

  • Vuex is stored in memory
  • Localstorage is stored locally as a file and can only store string data, which requires JSON’s Stringify and parse methods to handle. Memory is faster to read than hard disk

(2) Application scenarios

  • Vuex is a state management mode developed specifically for vue.js applications. It uses centralized storage to manage the state of all components of an application and rules to ensure that the state changes in a predictable way. Vuex is used to transfer values between components.
  • Localstorage is localstorage and is a method of storing data to a browser, typically when passing data across pages.
  • Vuex can be responsive to data, but localStorage cannot

(3) Permanence

The vuex value is lost when the page is refreshed, but the localStorage value is not.

Note: It is true that vuex can be replaced with localStorage for immutable data, but when two components share a data source (object or array), if one component changes the data source and expects the other component to respond to the change, localStorage cannot do so because of difference 1.

4. What is the difference between Redux and Vuex, their common idea

(1) Difference between Redux and Vuex

  • Vuex improved the Action and Reducer functions in Redux, and replaced Reducer with the mutations change function, without switch, only need to change the state value in the corresponding mutation function
  • Vuex doesn’t need to subscribe to the rerender function because of Vue’s automatic rerender feature, just generate a new State
  • The sequence of Vuex data stream is as follows: View calls store.mit to submit the corresponding request to the corresponding mutation function in Store -> Store change (vUE automatically renders when it detects the data change).

Commonly understood as vuex weakened dispatch, a change of store state through commit; Cancelling the action concept without passing in a specific action form to specify changes; Weaken reducer, directly transform data based on commit parameters, making the framework more simple;

(2) Common ideas

  • Single – data source
  • Change is predictable

Essentially: Both Redux and VUex are services to the idea of MVVM, a solution to pull data out of the view; Form: Vuex borrows from Redux and takes Store as the global data center for mode management.

5. Why Vuex or Redux

Because the method of parameter passing can be very tedious for multi-layer nested components, and there is no way to transfer state between sibling components. We often use parent-child components to reference multiple copies of state directly or through events to change and synchronize. These patterns are very fragile and often result in unmaintainable code.

The shared state of the components needs to be extracted and managed in a global singleton. In this mode, the tree of components forms a giant “view” where any component can pick up state or trigger behavior no matter where it is in the tree.

In addition, code becomes more structured and maintainable by defining and isolating concepts in state management and enforcing compliance with certain rules.

6. What are the attributes of Vuex?

There are five types, including State, Getter, Mutation, Action, and Module

  • State => Basic data (where data source is stored)
  • Getters => Data derived from base data
  • Mutations => Submit methods for changing data, simultaneous
  • Actions => acts like an decorator, wrapping mutations so it can be asynchronous.
  • Modules => Modular Vuex

7. What is the difference between Vuex and pure global objects?

  • 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.
  • You cannot change the state in the store directly. The only way to change the state in a store is to commit mutation explicitly. This makes it easy to track each state change, enabling us to implement tools to better understand our application.

8. Why can’t asynchronous operation be performed in Vuex mutation?

  • The only way to update any state in Vuex is mutation, and the asynchronous operation is implemented by submitting mutation via Action. This makes it easy to track each state change, which makes it possible to implement tools to better understand our application.
  • Each mutation was updated with a new state change so devTools could take a snapshot and then implement time-travel. If mutation supported asynchronous operations, there was no way to know when the state was updated, and no tracking of the state was possible, making debugging difficult.

9. What is the strict mode of Vuex, what is its function and how to open it?

In strict mode, an error is thrown whenever a state change occurs that is not caused by a mutation function. This ensures that all state changes are tracked by the debugging tool.

In the vuex.store constructor option, as shown below

const store = new Vuex.Store({
    strict:true,
})
Copy the code

10. How do I batch use Vuex’s 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

11. How do I reuse Vuex mutation in a component

Use the mapMutations helper function, and use it in the component

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

Then call this.setNumber(10) equivalent to call this.codestore.com MIT (‘SET_NUMBER’,10)

Six, Vue 3.0

1. What’s new to Vue3.0

(1) Change of monitoring mechanism

  • 3.0 will bring a proxy-based Observer implementation that provides reactive tracing with full language coverage.
  • Removed many of the limitations of the object.defineProperty-based implementation in Vue 2:

(2) Only attributes can be monitored, not objects

  • Detect the addition and removal of attributes;
  • Detect array index and length changes;
  • Supports Map, Set, WeakMap, and WeakSet.

(3) Template

  • The 2.x mechanism changed the scope slot so that the parent component would be re-rendered, while 3.0 changed the scope slot to function mode, which only affected the re-rendering of child components and improved rendering performance.
  • As for the render function aspect, vue3.0 will also make a number of changes to make it easier to use the API directly to generate the VDOM.

(4) Object-type component declaration

  • Components in vue2. X pass in a set of options declaratively, and TypeScript is combined with decorators, which are functional but cumbersome.
  • 3.0 changes the way components are declared to be class-like, making it easy to integrate with TypeScript

(5) Changes in other aspects

  • Support for custom renderers, which allows WEEX to be extended by custom renderers instead of forking the source code.
  • Fragment (multiple root nodes) and Protal (rendering components in other parts of the DOM) components are supported for specific scenarios.
  • Tree Shaking optimization provides more built-in functionality.

2. DefineProperty and proxy differences

Vue iterates through all properties in data during instance initialization and converts them all to getters/setters using Object.defineProperty. This way the setter is called automatically when the trace data changes.

Object.defineproperty is a non-shim feature in ES5, which is why Vue does not support IE8 and earlier browsers.

But this has the following problems:

  1. Vue cannot detect adding or deleting attributes of an object. Because objects added or removed are not being initialized for reactive processing, they can only pass$setTo invoke theObject.defineProperty()To deal with.
  2. Unable to monitor array subscript and length changes.

Vue3 uses a Proxy to monitor data changes. Proxy is a function provided in ES6. It is used to define custom behaviors of basic operations (such as attribute lookup, assignment, enumeration, function call, etc.). Compared to Object.defineProperty(), it has the following characteristics:

  1. Proxy directly represents the entire object rather than its properties, so that only one layer of Proxy can listen for all property changes in the peer structure, including new and deleted properties.
  2. Proxy can listen for array changes.

3. Why is Vue3.0 using proxy?

In Vue2, 0bject.defineProperty changes the original data, while Proxy creates a virtual representation of the object and provides handlers such as SET, GET, and deleteProperty that intercept when accessing or modifying properties on the original object. It has the following characteristics

  • No need to useVue.$setVue.$deleteTrigger response.
  • Omnidirectional array change detection eliminates Vue2 invalid boundary cases.
  • Supports Map, Set, WeakMap and WeakSet.

The responsiveness principle of Proxy implementation is the same as Vue2 implementation principle, and the implementation method is similar with minor differences:

  • Get Collection dependency
  • Set, delete and so on trigger dependencies
  • In the case of a collection type, you wrap the methods of a collection object: the original methods execute the dependence-dependent collection or triggering logic.

Vue Composition API in Vue 3.0?

In Vue2, the code is optionS-API-style, that is, a Vue component is created by populating (option) data, methods, computed, and so on. This style makes Vue extremely easy to use compared to React, but it also causes several problems:

  1. Vue development lacks an elegant way to share code between components due to the inflexible development approach of the Options API.
  2. Vue components are too dependentthisContext, there are some tricks behind Vue that make the development of Vue components seem contrary to JavaScript development principles, such as inmethodsIn thethisPointing to a component instance instead of pointingmethodsObject where. This also makes TypeScript difficult to use in Vue2.

In Vue3, the Options API was abandoned in favor of the Composition API. The Composition API essentially exposes the mechanics behind the Options API to users, giving them more flexibility and making Vue3 more suitable for TypeScript integration.

Here is a Vue3 component using the Vue Composition API:

<template>
  <button @click="increment">
    Count: {{ count }}
  </button>
</template>
 
<script>
// The Composition API exposes component properties as functions, so the first step is to import the required functions
import { ref, computed, onMounted } from 'vue'
 
export default {
  setup() {
// Use the ref function to declare a response attribute called count, corresponding to the data function in Vue2
    const count = ref(0)
 
Vue2 functions that need to be declared in methods option are now declared directly
    function increment() {
      count.value++
    }
 // This corresponds to the mounted declaration period in Vue2
    onMounted(() = > console.log('component mounted! '))
 
    return {
      count,
      increment
    }
  }
}
</script>
Copy the code

Obviously, the Vue Composition API makes Vue3’s development style more like native JavaScript, giving developers more flexibility

5. Composition API is like React Hook, what’s the difference

From the perspective of React Hook implementation, React Hook determines which useState state comes from the next rendering according to the order of useState calls, so the following restrictions appear

  • You cannot call a Hook in a loop, condition, or nested function
  • Make sure you always call the Hook at the top of your React function
  • UseEffect, useMemo, and other functions must determine dependencies manually

The Composition API is based on Vue’s responsive system implementation, compared to React Hook’s

  • Setup is called once for each component instantiation, whereas React Hook calls the Hook every time it rerenders, making React GC more stressful and slower than Vue
  • The Compositon API calls do not need to be ordered and can also be used in loops, conditions, and nested functions
  • Reactive system automatically realizes dependency collection, and the performance optimization of component parts is completed internally by Vue. However, React Hook needs to manually pass in dependencies and ensure the order of dependencies so that useEffect, useMemo and other functions can correctly capture dependent variables. Otherwise, component performance degrades due to incorrect dependencies.

The Compositon API looks better than React Hook, but the Compositon API is also designed with React Hook in mind.

Virtual DOM

1. Understanding of virtual DOM?

Essentially, the Virtual Dom is a JavaScript object that represents the Dom structure as an object. Abstract the page state into the form of JS objects, with different rendering tools, so that cross-platform rendering is possible. Through the transaction processing mechanism, the results of multiple DOM modifications are updated to the page at one time, thus effectively reducing the number of page rendering, reducing the number of DOM modification redrawing and rearrangement, and improving rendering performance.

The virtual DOM is an abstraction of the DOM, and this object is a more lightweight representation of the DOM. For example, Node.js does not have DOM. If you want to implement SSR, then one way is to use the virtual DOM, because the virtual DOM itself is a JS object. Before rendering the code to the page, VUE converts the code into an object (the virtual DOM). The actual DOM structure is described as an object and eventually rendered to a page. The virtual DOM caches a copy of the data each time it changes, and the current virtual DOM is compared to the cached one when it changes. The DIFF algorithm is encapsulated inside VUE, through which comparisons can be made. The changed changes can be modified during rendering, and the original unchanged changes can be rendered through the original data.

Is also a basic requirement of the modern front frame without manual DOM, on the one hand because of manual DOM cannot assure program performance, collaboration projects if you don’t strict review, there may be a developer write performance low code, on the other hand, more important is to omit the manual DOM manipulation can greatly improve the development efficiency.

2. Parsing process of virtual DOM

Virtual DOM parsing process:

  • Start by analyzing the DOM tree structure to be inserted into the document and representing it with a JS object, such as an element object that contains properties such as TagName, props, and Children. The JS object tree is then saved and the DOM fragment is inserted into the document.
  • When the state of the page changes, it is necessary to adjust the structure of the DOM of the page. First, an object tree is rebuilt according to the state of the change, and then the new object tree is compared with the old object tree to record the differences between the two trees.
  • Finally, the recorded discrepancies are applied to the actual DOM tree, and the view is updated.

3. Why the virtual DOM

(1) To ensure the lower limit of performance, without manual optimization, to provide acceptable performance take a look at the page rendering process: The following is a comparison between the real DOM operation and the Virtual DOM operation when modifying the DOM, to see the performance cost of their rearrangement and redrawing

  • Real DOM: Generate HTML string + rebuild all DOM elements
  • Virtual DOM: Generate vNode+ DOMDiff+ necessary DOM updates

Virtual DOM update DOM preparation takes more time, that is, at the JS level, which is extremely cheap compared to more DOM manipulation. The framework gives you the assurance that you don’t need to manually optimize and still give you decent performance, yu said in a community forum. (2) Cross-platform Virtual DOM is essentially an object of JavaScript, which can be operated conveniently across platforms, such as server-side rendering and UNIApp.

4. Is the virtual DOM really better than the real DOM

  • When rendering a large number of DOM for the first time, it is slower than innerHTML insertion due to the extra layer of virtual DOM computation.
  • Just as it guarantees a performance floor, it is faster to optimize for real DOM operations.

5. Principle of DIFF algorithm

When comparing old and new virtual DOM:

  • First, compare the node itself to determine whether it is the same node. If not, delete the node to create a new node for replacement
  • If it is the same node, conduct patchVnode to determine how to process the child nodes of the node. First, determine the situation where one party has child nodes and the other does not (if the new children do not have child nodes, remove the old child nodes).
  • Compare if both have child nodes, then perform updateChildren to determine how to operate on the children of these old and new nodes (diff core).
  • When matching, the same child nodes are found and compared recursively

In DIFF, only the child nodes of the same layer are compared, and the cross-level node comparison is abandoned, which makes the time complex and reduces the value O(n) from O(n3). That is to say, only when the old and new children have multiple child nodes, the core DIff algorithm is needed for same-level comparison.

6. Functions of keys in Vue

The role of key values in VUE can be considered in two cases:

  • The first case is when key is used in v-if. Since Vue renders elements as efficiently as possible, it is common to reuse existing elements rather than rendering them from scratch. Therefore, when using V-if to switch elements, if there is an element of the same type before and after the switch, the element will be reused. If it is the same input element, the user’s input will not be cleared before and after the switch, which is not desirable. Therefore, an element can be uniquely identified by using a key, in which case the element with the key will not be reused. The key is used to identify an individual element.
  • The second case is when keys are used in v-for. When v-for is used to update a list of rendered elements, it defaults to a “reuse in place” strategy. If the order of data items changes, Vue does not move DOM elements to match the order of data items, but simply reuses each element there. Therefore, by providing a key value for each list item, Vue can track the identity of the element for efficient reuse. The key is used to efficiently update and render the virtual DOM.

The key is a unique token for a Vnode in a Vue. With this key, diff operations can be more accurate and faster

  • The sameNode function a. keey === B. Keey can be compared with the sameNode function a. keey === B. So it’s more accurate.
  • Faster: Using the uniqueness of keys to generate map objects to obtain corresponding nodes, faster than traversal

7. Why not use index as key?

Using index as the key is essentially the same as not writing it, because no matter how the array is reversed, index is 0, 1, 2… This arrangement causes Vue to reuse the wrong old child nodes, doing a lot of extra work.