Vue的render函数

107 阅读1分钟

Vue的Render函数.png

1. Virtual DOM

  • 介绍
    • virtual DOM实际上是一个JavaScript对象,它相比于DOM运算会小很多。
      • 当状态发生变化的时候,前后的virtual DOM会进行diff运算,这样可以只更新部分改变了的DOM,而不是全部重绘。
  • 作用
    • Vue2使用了virtual DOM来更新DOM,这样减小le开销。
    • 虽然我们一般将组件模板写在template中,但是当Vue编译的时候,都会解析为virtual DOM。
  • VNode
    • virtual DOM是使用VNode描述的,可以理解成VNode就是virtual DOM。
  • VNode的创建
    • VNode要映射到真实的DOM需要经过一系列create、diff、patch等过程。
    • VNode的创建是通过createElement方法完成的。

2. Render函数

  • virtual dom

    • 在状态发生变化时,Vue会创建virtual dom,virtual dom实际上是一个javasc对象(这是为了只更新发生变化的部分,而不用全部重绘)
    • 对于正常的DOM节点
    <div id="main">
      <p>文本</p>
    </div>
    

    对应的JavaScript对象(也就是virtual dom会是这样)

    var vNode = {
      tag: 'div',
      attributes: {
        id: 'main',
      },
      children: [
        //子节点(p标签)
      ],
    }
    
    • vNode对象通过一些特定选项描述了真实的DOM结构。
  • 为什么要使用render函数

    • 有时候template不如render函数简洁,尤其当有大段逻辑重复的HTML的时候

      <!DOCTYPE html>
      <html>
          <head></head>
          <body>
              <div id="app">
                  <anchor :level="2" :title="特性"></anchor> <!-- 点击这个组件会跳转到页面中对应锚点位置 -->
                  <script type="text/x-template" id="anchor"> <!-- x-template写法,这样可以把组件的template部分拿出来写 -->
                      <div>
                          <h1 v-if="level === 1">
                              <a :href="'#' + title"> <!-- 这里使用的是锚点链接 -->
                                  <slot></slot>
                              </a>
                          </h1>
                      </div>
                      <div>
                          <h2 v-if="level === 2">
                              <a :href="'#' + title">
                                  <slot></slot>
                              </a>
                          </h2>
                      </div>
                      <div>
                          <h3 v-if="level === 3">
                              <a :href="'#' + title">
                                  <slot></slot>
                              </a>
                          </h3>
                      </div>
                  </script>
              </div>
          </body>
          <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
          <script>
              Vue.component('amchor',{
                  template: '#anchor',
                  props: {
                      level: {
                          type: number,
                          required: true,
                      },
                  }
              })
      
              const app = new Vue({
                  el: '#app',
              })
          </script>
      </html>
      
    • render函数与template的对比(使用template和render写的同一个组件)

      • 在这个例子中,template明显比render易读,所以绝大多数情况我们还是选择template,只有少数情况使用render。
      <!DOCTYPE html>
      <html>
          <head></head>
          <body>
              <div id="app">
                  <ele></ele>
                  <script type="text/x-template" id="ele">
                      <div id="element" :class="{show: isVisible}" @click="handleClick">
                          文本内容
                      </div>
                  </script>
              </div>
          </body>
          <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
          <script>
              Vue.component('ele',{
                  template: '#ele',
                  data: () => {
                      return{
                          isVisible: true,
                      }
                  },
                  methods: {
                      handleClick(){
                          console.log('click');
                      },
                  },
              })
      
              const app = new Vue({
                  el: '#app',
              })
          </script>
      </html>
      
      <!DOCTYPE html>
      <html>
          <head></head>
          <body>
              <div id="app">
                  <ele></ele>
              </div>
          </body>
          <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
          <script>
              Vue.component('ele',{
                  render: function(createElement){
                      return createElement(
                          'div',
                          {
                              class: { //作用类似于v-bind:class的API
                                  show: isVisible,
                              },
                              attrs: { //HTML的属性
                                  id: 'element',
                              },
                              on: { //绑定事件
                                  click: this.handleClick
                              },
                          },
                          '文本内容' //第3个参数实际上是子节点(也包括标签内的内容)
                      )
                  },
                  data: () => {
                      return {
                          isVisible: true,
                      }
                  },
                  methods: {
                      handleClick(){
                          console.log('click')
                      },
                  },
              })
      
              const app = new Vue({
                  el: '#app'
              })
          </script>
      </html>