Vue bidirectional binding principle

Vue. js adopts data hijacking combined with publiser-subscriber mode. It hijacks the setter and getter of each attribute through Object.defineProperty() to publish messages to subscribers when data changes and trigger corresponding listening callback.

The data was hijacked

Traversing the data property hijacks the setter and getter via Object.defineProprety

Vue relies on the collection process

  1. When new wacther, pushTarget is used to change the dep. target to Wacther, and the getter is triggered during render Vnode
function pushTarget (_target: ? Watcher) {
  if (Dep.target) targetStack.push(Dep.target)
  Dep.target = _target
}

updateComponent = () = > {
 vm._update(vm._render(), hydrating)
}

new Watcher(vm, updateComponent, noop, {
  before () {
    if (vm._isMounted) {
    callHook(vm, 'beforeUpdate')}}},true /* isRenderWatcher */)
Copy the code
  1. The getter triggers dep.depend() which executes dep.target.adddep (this), which executes the addDep method in Wacther
/ / Dep
depend () {
 if (Dep.target) { // dep. target = "watcher"
  Dep.target.addDep(this) // this =》dep}}Copy the code
  1. Dep is used as a parameter in addDep. Map has is used to determine whether the ID of the DEP already exists. If not, it is pushed to the stack (filter duplicate DEPs).
  2. Wacther is collected by executing the addSub method of the DEP just passed in
/ / Watcher

addDep (dep: Dep) {
 const id = dep.id
 if (!this.newDepIds.has(id)) {
 this.newDepIds.add(id)
 this.newDeps.push(dep)
 if (!this.depIds.has(id)) { // Prevent duplicate collection of DEPs
    dep.addSub(this) // deP collects watcher}}}Copy the code

The difference between Watch and COMPUTD

  • Computd is cached after the getter executes
  • Computd is suitable for performance-intensive computing scenarios
  • Watch is more of a listener, listening for a change and performing a callback

Function of Vue key

Key is the unique ID given to each Vnode. You can rely on the key to get the corresponding VNode in oldVnode more accurately and faster.

  • A more accurate

Because there is no local reuse with key, local reuse can be avoided in sameNode function A. key === B. key comparison. So it’s more accurate.

  • faster

The uniqueness of key is used to generate map objects to obtain corresponding nodes, which is faster than traversal

When there is no key or index as the key: for example, there may be no transition effect, or some nodes have bound data (form) state, and the state will be misaligned

Vue nextTick principle

  • It performs a callback after the DOM is updated, allowing us to manipulate the updated DOM

  • The ability to listen for DOM changes is a mutationObserver of the new H5 feature, but Vue is not implemented by listening for DOM changes

  • Instead, it uses the eventloop principle, because an eventloop task performs a DOM update after executing (completing an eventloop)

  • The cutoff point for completing a task is microtask completion, so Vue first uses promise. Then and then mutationObserver.

  • For compatibility then demote to the macro tasks setImmediate and setTimeout

// timerFunc collects asynchronous task events
function flushCallbacks () {
  pending = false
  const copies = callbacks.slice(0)
  callbacks.length = 0
  for (let i = 0; i < copies.length; i++) {
    copies[i]()
  }
}
let timerFunc

if (typeof Promise! = ='undefined' && isNative(Promise)) {
  const p = Promise.resolve()
  timerFunc = () = > {
    p.then(flushCallbacks)
    if (isIOS) setTimeout(noop)
  }
  isUsingMicroTask = true
} else if(! isIE &&typeofMutationObserver ! = ='undefined' && (
  isNative(MutationObserver) ||
  MutationObserver.toString() === '[object MutationObserverConstructor]'
)) {
  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)
  }
  isUsingMicroTask = true
} else if (typeofsetImmediate ! = ='undefined' && isNative(setImmediate)) {
  timerFunc = () = > {
    setImmediate(flushCallbacks)
  }
} else {
  timerFunc = () = > {
    setTimeout(flushCallbacks, 0)}}// Collect callback functions with callbacks
export function nextTick (cb? :Function, ctx? :Object) {
  let _resolve
  callbacks.push(() = > {
    if (cb) {
      try {
        cb.call(ctx)
      } catch (e) {
        handleError(e, ctx, 'nextTick')}}else if (_resolve) {
      _resolve(ctx)
    }
  })
  if(! pending) { pending =true
    timerFunc()
  }
  // $flow-disable-line
  if(! cb &&typeof Promise! = ='undefined') {
    return new Promise(resolve= > {
      _resolve = resolve
    })
  }
}
Copy the code

Diff Algorithm Flow (Patch)

CreateElm generates the real DOM for the first time. Then sameVnode is used to identify the same node and patchVNode child is used. If both the old node and the new node exist, updateChildren is used. If the old and new heads, tail and tail, and cross-samevNode pairs fail to be compared, key will be directly used to search the mapping table. If the same key node is found, sameVnode comparison will be performed. If the same key node is found, patchVNode of sub-node will be entered until the traversal is completed.

The new vue () process

What are the features of Vuex

First, Vuex is a state management mode developed specifically for Vue 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 core concepts focus on synchronous asynchronous implementation of Action mutation

Why can’t a Vue component data be an object

A Vue component can have multiple instances, and if you define data as an object, they share a single data object, and state changes affect all component instances.

The understanding of the MVVM

Realize model and View active data response and view update by way of instruction

What performance optimizations Vue has

  • Route lazy loading

  • Keep-alive cache page

  • Reuse dom with V-show

  • Long lists of pure data displays are frozen with Object.freeze

  • Long lists of big data with virtual scrolling

  • Timely event destruction

  • Server rendering SSR

Server side rendering principles

When the client requests the server, the server obtains the relevant data from the database, and renders the Vue components into HTML inside the server, and returns the data and HTML to the client. This process of converting data and components into HTML on the server is called the server side rendering SSR

Benefits of using SSR

  1. Is conducive to SEO

In fact, it is beneficial for crawlers to climb your page, because some page crawlers do not support JavaScript execution, and the non-SSR page captured by crawlers that do not support JavaScript execution will be an empty HTML page, and with SSR, these crawlers can obtain complete HTML structure data. Then included in the search engine.

  1. The white screen time is shorter

In contrast to client-side rendering, server-side rendering already gets an HTML text with data after the browser requests the URL. The browser simply parses the HTML and builds the DOM tree directly. The client rendering needs to get an empty HTML page first, at which time the page has entered a white screen. After that, it needs to load and execute JavaScript, request the back-end server to obtain data, and render the page with JavaScript before the final page can be seen. Especially in complex applications, JavaScript scripts need to be loaded. The more complex the application is, the more and larger the JavaScript scripts need to be loaded. As a result, the first screen of the application takes a long time to load, which reduces the experience.

What’s new with Vue3

  • Data hijacking: Use a proxy as a proxy
  • Virtual DOM reconstruction: V2 transforms static nodes into VDOM, and only constructs the VDOM of dynamic nodes
  • Tree-shaking is friendlier by moving most global apis and internal components to the ES module export
  • Support the ts
  • Composition API: New setup functions for code reuse (instead of mixins, which are prone to naming conflicts)

Vue2 reactive malpractice

The reactive process requires recursive traversal, which consumes a lot of energy. Adding or deleting attributes cannot listen to arrays. The reactive process requires additional implementation, such as Map, Set, and Class

Life cycle 2. mapping between X and Composition

  • beforeCreate -> use setup()

  • created -> use setup()

  • beforeMount -> onBeforeMount

  • mounted -> onMounted

  • beforeUpdate -> onBeforeUpdate

  • updated -> onUpdated

  • beforeDestroy -> onBeforeUnmount

  • destroyed -> onUnmounted

  • errorCaptured -> onErrorCaptured

Vue component communication

  1. Props ★★ (Father to son)

  2. Emit /emit/emit/ ON ★★ Event Bus (cross level communication)

  3. Vuex ★★★ (common status management) Advantages: All pages can be accessed by storing data at one time

  4. Parent/parent/parent/children (parent = (not recommended) disadvantages: not across levels

  5. Attrs/attrs/attrs/listeners (are available if you don’t understand it is not recommended, and the interviewer said this one)

  6. Provide /inject★★★ (Advanced usage = Recommended) Advantages: Easy to use Disadvantages: Not responsive

v-model vs .sync

The difference between:

A component can have multiple properties with the.sync modifier, which can “bidirectionally bind multiple” prop “at the same time, unlike the V-Model, which has only one for each component

Usage Scenarios:

V-model is more about the final operation result, which is the result of bidirectional binding. It is value, which is a change operation

Sync is more about a variety of states. It’s about exchanging states, it’s about status, it’s about update

The V-model can be used in scenarios where only the child component updates the parent component as follows:

<CreativityGroup: plantemplatemodel. sync="planParams"/> true }) formModleChange(nVal) { this.$emit('input', nVal) }Copy the code

Examples of v-model vs. sync usage

<template>
  <div>
    my myParam {{ value }}<br />
    paramsync {{ paramsync }}
    <button type="button" @click="change">change my</button>
  </div>
</template>

<script>
export default {
  props: {
    value: {
      type: String,
      default: ""
    },
    paramsync: {
      type: Number,
      default: 0
    }
  },
  computed: {
    value1: {
      set(val) {
        this.$emit("input", val);
      },
      get() {
        return this.value;
      }
    }
  },
  methods: {
    change() {
      this.value1 = "rtrtr";
      console.log("this.value", this.value);
    //   this.paramsync = 78;
    // this.$emit('input','更新之后')
      this.$emit("update:paramsync",5555);
    }
  }
};
</script>
Copy the code

Vue life cycle

  1. BeforeCreate: after the instance is initialized, it is called before the Data Observe and Event/Watcher events are configured. In this case, data such as data and props cannot be accessed.

  2. Created: Called immediately after the instance is created, when the instance has completed data observer, property and method operations, watch/ Event callback, mount phase has not started, and $EL is not available.

  3. Beforemount: Called before the mount begins, the associated render function is called for the first time.

  4. Mounted: When mounted is called, vm. El is replaced by the newly created vm. When Mounted is called, vm. El is also in the document. Note Mounted does not ensure that all child components are mounted together.

  5. Beforeupdata: called when data is updated, occurs before the virtual DOM is patched. In this case, it is appropriate to access the existing DOM before the update, for example, manually remove the added event listener.

  6. Updated: This hook is called after the virtual DOM is re-rendered and patched due to data changes. When this hook is called, the component DOM is updated to perform DOM-dependent operations. In most cases, the status should change during this time. If you need to change it, it is best to use Watcher or calculated properties instead. Note that the updated does not guarantee that all child components can be redrawn together.

  7. Beforedestory: called before instance destruction. At this point, the instance is still available.

  8. Destroyed: Called after the instance is destroyed. All instructions for the Vue instance are unbound, all event listeners are removed, and all subinstances are destroyed.

Vue the compile process

The compilation process as a whole is divided into parsing, optimization and generation

Resolution – the parse

Parsers parse templates into abstract syntax trees that can be optimized or code generated based on the AST

Optimization – optimize

The optimizer’s job is to find and label static subtrees in the AST. Static subtrees are nodes that never change in the AST, such as plain text nodes. The benefit of marking static subtrees: The static subtree can be skipped every time you re-render and do not need to create a patch in the virtual DOM for a new node for the static subtree

Code generation – generate

Convert the AST into the content of the rendering function, which is the code string.

Vue2 vs Vue3

Disadvantages of Vue2 responsiveness: The reactive process requires recursive traversal, which costs a lot. New or deleted attributes cannot listen to arrays. Responsiveness requires additional implementation of Map, Set, and Class

Vite principle

To be updated