vue2源码-六、根据render函数生成vnode

发布时间 2023-04-16 19:02:43作者: 楸枰~

根据render函数生成vnode

  1. 上文介绍

    上面已经将模板编译成了render函数,下面就要使用render函数,从而完成渲染的操作:

    首先,根据render函数生成虚拟节点;然后根据虚拟节点+真实数据生成真实节点。

    实现mountComponent方法,完成渲染

  2. 虚拟节点生成

    • 封装vm._render方法。

        Vue.prototype._render = function () {
          // 让with指中的this指向vm
          // 当渲染的时候会去实例取值,就可以将属性和视图绑定在一起
          return this.$options.render.call(this); // 通过ast语法转义后生成的render方法
        };
      

      _render被调用时,内部会调用_c_v_s三个方法

      所以,在vm._render方法中,需要完成以下几件事:

      • 调用render函数
      • 提供_c_vs三个方法
        Vue.prototype._c = function () {
          return createElementVNode(this, ...arguments);
        };
      
        Vue.prototype._v = function () {
          return createTextVNode(this, ...arguments);
        };
      
        Vue.prototype._s = function (value) {
            // 不是对象
          if (typeof value !== "object") return value;
            // 是对象,返回字符串
          return JSON.stringify(value);
        };
      
    • _s方法

      如上面所示。

    • 实现_c_v方法

      观察_c_v调用了两个方法,因此实现两个方法:

      export function createElement() { 
        // 返回元素虚拟节点
      }
      export function createText() {  
        // 返回文本虚拟节点
      }
      

      这两个方返回虚拟节点。

      实现:

      // h() _c()
      
      export function createElementVNode(vm, tag, data = {}, ...children) {
        if (data == null) {
          data = {}
        }
        let key = data.key
        if (key) {
          delete data.key
        }
        return vnode(vm, tag, key, data, children)
      }
      
      // _v()
      export function createTextVNode(vm, text) {
        return vnode(vm, undefined, undefined, undefined, undefined, text)
      }
      
      // ast一样吗?ast做的是语法层面的转化,他描述的是语法本身
      // 我们的虚拟dom是描述的dom元素,可以增加自定义属性
      function vnode(vm, tag, key, data, children, text) {
        return {
          vm, // 是谁的虚拟节点
          tag, // 标签
          key, // 键
          data, // 数据
          children,  // 孩子
          text, // 文本
        }
      }
      
  3. 总结生成虚拟节点

    根据render函数,生成vnode

    • 封装vm._render返回虚拟节点
    • _s_c_v的实现