In-depth understanding of the render function of Vue components

    Generally speaking, when we write Vue.js components, the template is <template>included , but it is not the final content. Template is just a developer-friendly syntax. You can see the DOM nodes at a glance and it is easy to maintain. During the Vue.js compilation phase, it will be parsed into Virtual DOM.

    Compared with DOM operations, Virtual DOM is calculated based on JavaScript, so the overhead will be much smaller.

    A normal DOM node looks like this in HTML:

<div id="main">
  <p>文本内容</p>
  <p>文本内容</p>
</div>

     JavaScript objects created with Virtual DOM generally look like this:

const vNode = {
  tag: 'div',
  attributes: {
    id: 'main'
  },
  children: [
    // p 节点
  ]
}

     The vNode object describes the actual DOM structure with some specific options.

     In Vue.js, for most scenarios, using template is sufficient, but if you want to fully utilize the programming capabilities of JavaScript, or in some specific scenarios, you need to use the Render function of Vue.js.

Render function

     Just like the Virtual DOM example introduced above, the Render function of Vue.js has a similar syntax and requires the use of some specific options to rewrite the content of the template into a JavaScript object.

     For junior front-end engineers, or those who want to quickly build a website, it is more difficult to directly use the Render function to develop Vue.js components than template. The reason is that the Render function returns a JS object without the traditional DOM hierarchical relationship. With the use of if, Else, for and other statements split the nodes into different JS objects and then assemble them. If the template is complex, the Render function will be difficult to read and maintain. Therefore, for most component development and business development, we can just use template syntax directly. There is no need to specifically use the Render function, which will only increase the burden and give up the biggest advantage of Vue.js (React has no template syntax) .

       Many developers who are learning Vue.js tend to "avoid" when encountering the Render function, or simply give up on this part. This is not a problem, because you can still write excellent Vue.js programs without the Render function. However, the Render function is not as complicated as imagined, but there are so many configuration items that it is difficult to remember. But in the final analysis, the Render function only has 3 parameters.

       Let’s look at a comparison of template and Render writing methods:

<template>
  <div id="main" class="container" style="color: red">
    <p v-if="show">内容 1</p>
    <p v-else>内容 2</p>
  </div>
</template>
<script>
  export default {
    data () {
      return {
        show: false
      }
    }
  }
</script>
export default {
  data () {
    return {
      show: false
    }
  },
  render: (h) => {
    let childNode;
    if (this.show) {
      childNode = h('p', '内容 1');
    } else {
      childNode = h('p', '内容 2');
    }
    
    return h('div', {
      attrs: {
        id: 'main'
      },
      class: {
        container: true
      },
      style: {
        color: 'red'
      }
    }, [childNode]);
  }
}

  Here h, that is createElement, is the core of the Render function. It can be seen that the v-if / v-else and other instructions in the template have been replaced by JS's if / else , and v-for will naturally be replaced by the for statement.

h has 3 parameters, namely:

  1. The element or component to be rendered can be an html tag, component option or a function (not commonly used). This parameter is required. Example:

    // 1. html 标签
    h('div');
    // 2. 组件选项
    import DatePicker from '../component/date-picker.vue';
    h(DatePicker);
  2. Data objects corresponding to attributes, such as component props, element classes, bound events, slots, custom instructions, etc. This parameter is optional. The Render configuration items mentioned above refer to this parameter. The complete configuration and examples of this parameter can be viewed in the Vue.js documentation. There is no need to remember them all.

  3. Child node, optional, String or Array, which is also an h. Example:

    [
      '内容',
      h('p', '内容'),
      h(Component, {
        props: {
          someProp: 'foo'
        }
      })
    ]
    Constraints on render function

         In all component trees, if a vNode is a component or a slot containing a component, then the vNode must be unique. Both of the following examples are incorrect .

    // 局部声明组件
    const Child = {
      render: (h) => {
        return h('p', 'text');
      }
    }
    
    export default {
      render: (h) => {
        // 创建一个子节点,使用组件 Child
        const ChildNode = h(Child);
        
        return h('div', [
          ChildNode,
          ChildNode
        ]);
      }
    }
    {
      render: (h) => {
        return h('div', [
          this.$slots.default,
          this.$slots.default
        ])
      }
    }

      Repeated rendering of multiple components or elements can be solved through a loop and factory function:

    const Child = {
      render: (h) => {
        return h('p', 'text');
      }
    }
    
    export default {
      render: (h) => {
        const children = Array.apply(null, {
          length: 5
        }).map(() => {
          return h(Child);
        });
        return h('div', children);
      }
    }
    Render function usage scenarios

     As mentioned above, it is generally not recommended to use the Render function directly. Using template is enough. In Vue.js, the scenarios for using the Render function mainly include the following four points:

  4. Use two identical slots. In the template, Vue.js does not allow the use of two identical slots. For example, the following example is wrong:

    <template>
      <div>
        <slot></slot>
        <slot></slot>
      </div>
    </template>

    You can use a deep clone method of VNode nodes.

  5. In the SSR environment (server-side rendering), if the template is not written in a conventional way, such as the component instance generated through the Vue.extend and new Vue constructs, it will not be compiled and an error will be reported in SSR. At this time, you need to use the render function to solve the problem.

  6. In the runtime version of Vue.js, if you use Vue.extend to manually construct an instance and use the template option, an error will be reported. The solution is also very simple, just rewrite template as Render. It should be noted that when developing independent components, you can configure the Vue.js version to make the template option available, but this is in your own environment, and the user's Vue.js version cannot be guaranteed, so for components provided to others , it is necessary to consider compatibility with the runtime version and SSR environment.

  7. For a Vue.js component, some content needs to be passed from the parent to display. If it is text or the like, it can be passed directly. propsIf the content has a style or a more complex html structure, you can use v-htmlinstructions to render it. The parent What is passed is still an HTML Element string, but it can only parse normal html nodes and has XSS risks. When you need to customize the display content to the greatest extent, you need Renderthe function, which can render a complete Vue.js component. You might say, wouldn’t it be better to use slot? Indeed, the role of slot is to distribute content, but in some special components, slot may not work. For example, a table component Tableonly receives two props: column configuration columns and row data. However, the cells in a certain column are not as simple as just displaying the data. They may have some complex operations. In this scenario, only slot is used. It doesn't work. There is no way to determine which column the slot belongs to. At this time, using the render function is a solution.

end

         Okay, the above is about the render function of the Vue component. If you have any questions, please leave a comment below~

Guess you like

Origin blog.csdn.net/quxuetrip/article/details/131787143