2020年11月18日

数据驱动模型(3)-渲染

作者 rourou

虚拟DOM生成带数据的虚拟DOM

  • 该方法需要参数:虚拟DOM(vnode)、实例化对象时的数据(data)
  • 判断节点类型(vnode.type):区分元素节点和文本节点
  • 元素节点:通过data数据直接实例化VNode类(定义方式见数据驱动模型(2)虚拟dom块)生成dom;若含有子元素(vnode.children)则采用递归方式调用本方法
  • 文本节点:采用通过正则表达式结合replace 方法获取需替换的值data,进行实例化VNode类
var rz = /\{\{(.+?)\}\}/g;
    function combine(vnode, data){
      var tag = vnode.tag;
      var attr = vnode.attr;
      var value = vnode.value;
      var type = vnode.type;
      var children = vnode.children;
      var _vNode = null;
      if(type == 1){
        // 元素节点
        _vNode =new VNode(tag, attr, value, type);

        for(var i=0;i<children.length;i++){
          _vNode.getData( combine(children[i], data) )
        }

      }else if(type == 3){
        // 文本节点
        var res = value.trim().replace(rz, function(_,g){
          return getValueByPath(data, g);
        })
        _vNode =new VNode(tag, attr, res, type);

      }
      return _vNode;
    }
    function getValueByPath(obj, path){
      var arr = path.split('.');
      let res = obj;
      let prop;
      // arr.shift()取出数组的第一个值
      while( prop = arr.shift() ){
        res = res[ prop ];
      }
      return res;
    }

带数据的虚拟DOM生成真是DOM(html)

  • 该方法parseDom的参数包含:带数据的虚拟Dom(res)。判断节点类型。
  • 元素节点时,创建元素节点(document.createElement);使用setAttribute方法绑定上相关属性。考虑子元素(children)则采用递归方式调用本方法parseDom
  • 文本节点时,直接创建文本节点(document.createTextNode)
function parseDom (res){
      let tag = res.tag;
      let type = res.type;
      let value = res.value;
      let attr = res.attr;
      let children = res.children;
      if(type == 1){
        if(tag != undefined){
          var ele = document.createElement(tag);
        }
        if(attr != undefined){
          for(var i in attr){
            ele.setAttribute(i,attr[i]);
          }
        }
        if(children.length != 0){
          for(var i=0;i<children.length;i++){
            val = ele.appendChild(parseDom(children[i]));
          }
        }
      }else if(type == 3){
        var ele = document.createTextNode(value);
      }
      return ele;
    }