美文网首页
vue模板实现4-高效更新

vue模板实现4-高效更新

作者: 恒星的背影 | 来源:发表于2018-05-13 11:39 被阅读0次
    • 这次的改动大一些,目标是希望在数据更改时不必重新遍历 dom,只更新对应的文本。
    • 思路是首先遍历 dom,将所有文本元素 ( nodeName === '#text' ) 和对应的数据绑定起来,即根据数据可以直接对应到 dom 节点。
    • 接下来的工作就是监控数据变化了,数据变化时需要知道被改的数据是哪个,但 defineProperty 不能做到,因为它的 set 中参数只有新的 value。所以使用了proxy,proxy 可以直接对整个 json 进行代理,使用起来更加方便。
    • 总的流程:
      先用 proxy 对 data 代理,在 set 中设置 update( ),数据更新时,直接更新对应文本节点
      遍历 dom,将数据和对应文本节点绑定起来
      遍历 data,将所有的 {{ }} 替换
    class Vue {                                            // Vue 类
      constructor(obj) {
        let {el, data} = obj
        const node = document.querySelector(el)
        const dataBindNode = {}
    
        data = new Proxy(data, {
          get(tar, key){
            return tar[key]
          },
          set(tar, key, val){
            tar[key] = val
            updateText(dataBindNode[key], data)
          }
        })
    
        this.data = data
    
        traverseNode(node, data, dataBindNode)
    
        for(let key in dataBindNode) {          // 第一次更新
          updateText(dataBindNode[key], data)
        }
      }
    }
    
    const updateText = (node, data) => {                    // 更新数据对应的文本节点
      const reg = /{{\w+}}/g
      const arr = node.text.match(reg) || []
      let text = node.text
    
      arr.forEach((item)=>{
        const name = item.slice(2, -2)
    
        if(data[name]) {
          node.node.textContent = text = text.replace(item, data[name])
        }
      })
    }
    const traverseNode = (node, data, dataBindNode) => {      // 遍历
      node.childNodes.forEach(item => {
        if(item.nodeName === '#text') {
          bindNode(item, data, dataBindNode)
        }
        else {
          traverseNode(item, data, dataBindNode)
        }
      });
    }
    
    const bindNode = (node, data, dataBindNode) => {          // 绑定
      const reg = /{{\w+}}/g
      const arr = node.textContent.match(reg) || []
    
      arr.forEach((item)=>{
        const key = item.slice(2, -2)
        if(data[key]) {
          dataBindNode[key] = {}
          dataBindNode[key].node = node
          dataBindNode[key].text = node.textContent
        }
        else { }  // 数据未定义却使用
      })
    }
    

    相关文章

      网友评论

          本文标题:vue模板实现4-高效更新

          本文链接:https://www.haomeiwen.com/subject/ozdhdftx.html