Introduction to the

Vue functional components are not used by most people in the development process, even the official document location is relatively obscure, but when we do performance optimization on the project, they are a good choice. This article provides a systematic overview of the functional component initialization process. You will learn the following:

  • What is a functional component
  • The difference between a functional component and a normal component
  • vueSimilar performance optimization points

What is a functional component

A functional component is a stateless component that has no data, computed, watch, or lifecycle methods. It also has no this context and only props is passed as an argument. In development, there are many components that only use props and slots, which can be distilled into functional components. The simplest functional components are as follows:

Vue.component('my-component', {
  functional: true.// Props is optional
  props: {
    // ...
  },
  // To make up for missing instances
  // Provide the second argument as context
  render: function (createElement, context) {
    // ...}})Copy the code

The difference between a functional component and a normal component

The component instantiation process is roughly divided into four steps: state initialization -> template compilation -> VNode generation -> conversion to the real DOM. Next, compare common configuration items for normal and functional components to see the differences.

Function point name Common components Functional component describe
vm Y N Component scope
hooks Y N Lifecycle hook
data Y N Data object declaration
computed Y N Calculate attribute
watch Y N The listener
props Y Y attribute
children Y Y An array of VNode children
slots Y Y A function that returns an object containing all slots
scopedSlots Y Y The object of the scope slot
injections Y Y Dependency injection
listeners Y Y Event listeners
parent Y Y A reference to the parent component

As you can see from the table above, the biggest difference between normal components and functional components is that functional components have no independent scope and no responsive data declarations. Having no independent scope has the following advantages:

  1. No component instantiation (new vnode.com ponentOptions Ctor (options), functional component to get VNode is only the ordinary function call

    • No public property, method copy
    • Non-lifecycle hook calls
  2. Functional components mount directly to the parent component, shortening the first rendering, diff update path

    • Functional components are generated in the parent componentVNode, functional componentsrenderMethod will be called, generateVNodeMount to the parent componentchildren,patchStages can be directly translated into realityDOM, the common components are increateElmGo to the component initialization process.
    • diffWhen updated, the functional component is calledrender, directly create commonVNode, while normal components are createdVNodeContains the component scope,diffOperation, there are additional callsupdateChildComponentUpdate attributes, custom events, etc., the call link will be long.

Vue performance optimization points

The performance gains from functional components can be found in shorter render paths, which are similar to browser redraw backflow, and reduced levels of component nesting, which can reduce time complexity.

No matter what kind of performance optimization, the optimization can be done from the code level, is undoubtedly the least expensive, although sometimes the effect is not very obvious, but it adds up. In VUE, there are many similar points that can improve the efficiency of code execution.

Reasonable statementdataData, ensure thatdataIt states that the data is required

Many times there is data that is not necessarily declared in data, such as data that needs to be shared within components but does not need to be processed in a responsive manner. Data in data, objects declare their depth first with Object.defineProperty, and arrays intercept basic operation methods. Unnecessary statements can lead to meaningless data hijacking.

The rational use ofcomputedwithwatch

The biggest difference between computed and Watch is that computed is lazy-loaded. Lazy loading is mainly reflected in two aspects:

  1. When a dependency state changes, it does not trigger immediately, but only changes the current stateWatcherThe instancedirtyAttribute values fortrue
  2. When an operation is performed on a calculated property value, if and only ifwatcher.dirty === true, will trigger the calculation

The above two features can avoid some unnecessary code execution, as shown below:

// src\core\instance\state.js
function createComputedGetter (key) {
  return function computedGetter () {
    // Get a Watcher instance of computed properties on the instance
    const watcher = this._computedWatchers && this._computedWatchers[key]
    if (watcher) {
      // Watcher's update method is called to set dirty to true if and only if computed dependency properties change &&
      if (watcher.dirty) {
        // Call the get method to get the computed value
        watcher.evaluate()
      }
      if (Dep.target) {
        watcher.depend()
      }
      return watcher.value
    }
  }
}
// src\core\observer\watcher.js
update () {
  // computed watcher lazy === true
  if (this.lazy) {
    // Flag lazy execution for executable status, false does not perform calculation property calculations
    this.dirty = true
  } else if (this.sync) { // Synchronize execution
    this.run()
  } else {
    // Put the current watcher into the Watcher queue
    queueWatcher(this)}}Copy the code

V-for binds the key value

V-for loop defines key values to facilitate accurate finding of diff comparison nodes and avoid some meaningless comparison.

Normal diff: The diff process ends if and only if a node is traversed

Diff with key: Maintains a Hash table based on the key value, and accurately locates and updates the target node each time. The diff process ends when and only when the traversal of a node is complete

thinking

In VUE, many of the performance optimizations are about shortening the code execution path, especially when there is a lot of computational logic, and the performance improvement can be visible to the eye. In practice, there are many scenarios that can use this kind of optimization method. For example, keyword highlighting matching is the simplest example. To do this, the following steps are required:

  1. Get matching keywords, format them (escape meaningful strings in the regular expression)
  2. Dynamically generate a matching regular expression
  3. Proceed according to the regular expressionreplaceoperation

Sometimes, we can omit the first and second steps and directly execute the third step, because the input keywords may have the same, so we can cache the string and regular expression in the Map. The next match, if there is a cache, we can directly take it from the cache.

Vue template compilation uses this feature, each time the compiled template string as the key value, render method as the value, cache, if you encounter the same template, can save the compilation process, bring a certain performance improvement.

summary

Developing good coding habits is also a good improvement for personal ability.