加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 资源网站 > 资源 > 正文

手动实现一个虚拟DOM算法

发布时间:2020-12-14 23:56:58 所属栏目:资源 来源:网络整理
导读:发现一个好文:《》 文章写得非常详细,仔细看了一遍代码,加了一些注释。其实还有有一些地方看的不是很懂(毕竟我菜qaq 先码 有时间研究下diff算法 util.js _ = span style="color: #008000;"/ span style="color: #008000;" 获取一个对象的类型 匹配 '[obj

发现一个好文:《》

文章写得非常详细,仔细看了一遍代码,加了一些注释。其实还有有一些地方看的不是很懂(毕竟我菜qaq 先码 有时间研究下diff算法

util.js

_ =<span style="color: #008000;">/<span style="color: #008000;">

  • 获取一个对象的类型
  • 匹配 '[objects' (s 是空白字符) 或 ']' 并替换为空
  • 也就是可以将 [object Array] 变为 Array
  • @param {Object} obj
    <span style="color: #008000;">*/<span style="color: #000000;">
    _.type = <span style="color: #0000ff;">function<span style="color: #000000;">(obj) {
    <span style="color: #0000ff;">return Object.prototype.toString.call(obj).replace(/[objects|]/g,''<span style="color: #000000;">)
    }

<span style="color: #008000;">/<span style="color: #008000;">

  • 判断一个对象是否是数组
  • @param {Object} list
    <span style="color: #008000;">*/<span style="color: #000000;">
    .isArray = <span style="color: #0000ff;">function<span style="color: #000000;"> isArray(list) {
    <span style="color: #0000ff;">return
    .type(list) === 'Array'<span style="color: #000000;">
    }

<span style="color: #008000;">/<span style="color: #008000;">

  • 判断一个对象是否为 String
    <span style="color: #008000;">*/<span style="color: #000000;">
    .isString = <span style="color: #0000ff;">function<span style="color: #000000;"> isString(list) {
    <span style="color: #0000ff;">return
    .type(list) === 'String'<span style="color: #000000;">
    }

<span style="color: #008000;">/<span style="color: #008000;">

  • 用于将 类数组对象 变为数组 比如 nodeList,argument 等带有 length 属性的对象
  • @param {*} arrayLike
  • @param {int} index 从第几个元素开始
    <span style="color: #008000;">*/<span style="color: #000000;">
    _.slice = <span style="color: #0000ff;">function<span style="color: #000000;"> slice(arrayLike,index) {
    <span style="color: #0000ff;">return<span style="color: #000000;"> Array.prototype.slice.call(arrayLike,index)
    }

<span style="color: #008000;">/<span style="color: #008000;">

  • 获取 value 表达式的布尔值
  • @param {} value
    <span style="color: #008000;">
    /<span style="color: #000000;">
    _.truthy = <span style="color: #0000ff;">function<span style="color: #000000;"> truthy(value) {
    <span style="color: #0000ff;">return !!<span style="color: #000000;">value
    }

<span style="color: #008000;">/<span style="color: #008000;">

  • 对数组中每一个元素执行 fn (相当于map?
  • @param {*} array
  • @param {} fn
    <span style="color: #008000;">
    /<span style="color: #000000;">
    _.each = <span style="color: #0000ff;">function<span style="color: #000000;"> each(array,fn) {
    <span style="color: #0000ff;">for (<span style="color: #0000ff;">var i = 0,len = array.length; i < len; i++<span style="color: #000000;">) {
    fn(array[i],i)
    }
    }

<span style="color: #008000;">/<span style="color: #008000;">

  • 为 DOM 节点设置属性
    <span style="color: #008000;">/<span style="color: #000000;">
    _.setAttr = <span style="color: #0000ff;">function<span style="color: #000000;">(node,key,value) {
    <span style="color: #0000ff;">switch<span style="color: #000000;">(key) {
    <span style="color: #0000ff;">case 'style'<span style="color: #000000;">:
    node.style.cssText =<span style="color: #000000;"> value
    <span style="color: #0000ff;">break
    <span style="color: #0000ff;">case 'value'<span style="color: #000000;">:
    <span style="color: #0000ff;">var tagName = node.tagName || ''<span style="color: #000000;">
    tagName =<span style="color: #000000;"> tagName.toLowerCase()
    <span style="color: #0000ff;">if (tagName === 'input' || tagName === 'textarea'<span style="color: #000000;">) {
    node.value =<span style="color: #000000;"> value
    } <span style="color: #0000ff;">else<span style="color: #000000;"> {
    node.setAttribute(key,value)
    }
    <span style="color: #0000ff;">break
    <span style="color: #0000ff;">default<span style="color: #000000;">:
    node.setAttribute(key,value)
    <span style="color: #0000ff;">break<span style="color: #000000;">
    }
    }
    <span style="color: #008000;">/
    <span style="color: #008000;">*

  • 将类数组类型转化为数组类型

  • @param {Object} listLike

  • ( 和 slice 有什么区别呢?????
    <span style="color: #008000;">*/<span style="color: #000000;">
    _.toArray = <span style="color: #0000ff;">function<span style="color: #000000;"> toArray(listLike) {
    <span style="color: #0000ff;">if (!listLike) <span style="color: #0000ff;">return<span style="color: #000000;"> []

    <span style="color: #0000ff;">var list =<span style="color: #000000;"> []

    <span style="color: #0000ff;">for (<span style="color: #0000ff;">var i = 0,len = listLike.length; i < len; i++<span style="color: #000000;">) {
    list.push(listLike[i])
    }

    <span style="color: #0000ff;">return<span style="color: #000000;"> list
    }

element.js

_ = require('./util'
  • 用来表示虚拟 DOM 节点的数据结构

  • @param {String} tagName 节点类型

  • @param {Object} props 节点属性 键值对形式 可以选填

  • @param {Array<Element|String>} children 节点的子元素 或者文本

  • @example Element('div',{'id': 'container'},[Element('p',['the count is :' + count])])
    <span style="color: #008000;">*/
    <span style="color: #0000ff;">function<span style="color: #000000;"> Element(tagName,props,children) {
    <span style="color: #008000;">//<span style="color: #008000;"> var e = Element(tagName,children)
    <span style="color: #008000;">//<span style="color: #008000;"> 并不会让 e instanceof Element 为 true 要加 new 关键字才可以哦
    <span style="color: #0000ff;">if (!(<span style="color: #0000ff;">this <span style="color: #0000ff;">instanceof<span style="color: #000000;"> Element)) {
    <span style="color: #008000;">//<span style="color: #008000;"> 如果 children 不是数组且不为空 就把第三个参数以及后面的参数都作为 children
    <span style="color: #0000ff;">if (!.isArray(children) && children != <span style="color: #0000ff;">null<span style="color: #000000;">) {
    <span style="color: #008000;">//<span style="color: #008000;"> children 去掉非空子元素
    children =
    .slice(arguments,2<span style="color: #000000;">).filter(.truthy)
    }
    <span style="color: #0000ff;">return <span style="color: #0000ff;">new<span style="color: #000000;"> Element(tagName,children)
    }
    <span style="color: #008000;">//<span style="color: #008000;"> 如果属性是数组类型 证明没有传属性 第二个参数就是 children
    <span style="color: #0000ff;">if<span style="color: #000000;"> (
    .isArray(props)) {
    children =<span style="color: #000000;"> props
    props =<span style="color: #000000;"> {}
    }

    <span style="color: #0000ff;">this.tagName =<span style="color: #000000;"> tagName
    <span style="color: #0000ff;">this.props = props ||<span style="color: #000000;"> {}
    <span style="color: #0000ff;">this.children = children ||<span style="color: #000000;"> []
    <span style="color: #008000;">//<span style="color: #008000;"> void后面跟一个表达式 void操作符会立即执行后面的表达式 并且统一返回undefined
    <span style="color: #008000;">//<span style="color: #008000;"> 可以为节点添加一个属性 key 以便重新排序的时候 判断节点位置的变化
    <span style="color: #0000ff;">this.key = props ? props.key : <span style="color: #0000ff;">void 0

    <span style="color: #008000;">//<span style="color: #008000;"> count 统计不包含文本元素 一共有多少子元素
    <span style="color: #0000ff;">var count = 0<span style="color: #000000;">

    _.each(<span style="color: #0000ff;">this.children,<span style="color: #0000ff;">function<span style="color: #000000;">(child,i) {
    <span style="color: #0000ff;">if (child <span style="color: #0000ff;">instanceof<span style="color: #000000;"> Element) {
    count +=<span style="color: #000000;"> child.count
    } <span style="color: #0000ff;">else<span style="color: #000000;"> {
    children[i] = '' +<span style="color: #000000;"> child
    }
    count++<span style="color: #000000;">
    })

    <span style="color: #0000ff;">this.count =<span style="color: #000000;"> count
    }

  • <span style="color: #008000;">/<span style="color: #008000;">

    • 将虚拟DOM 渲染成真实的DOM元素
      <span style="color: #008000;">*/<span style="color: #000000;">
      Element.prototype.render = <span style="color: #0000ff;">function<span style="color: #000000;">() {
      <span style="color: #008000;">//<span style="color: #008000;"> 根据 tag 创建元素
      <span style="color: #0000ff;">var el = document.createElement(<span style="color: #0000ff;">this<span style="color: #000000;">.tagName)
      <span style="color: #0000ff;">var props = <span style="color: #0000ff;">this<span style="color: #000000;">.props
      <span style="color: #008000;">//<span style="color: #008000;"> 为元素添加属性
      <span style="color: #0000ff;">for (<span style="color: #0000ff;">var propName <span style="color: #0000ff;">in<span style="color: #000000;"> props) {
      <span style="color: #0000ff;">var propValue =<span style="color: #000000;"> props[propName]
      .setAttr(el,propName,propValue)
      }
      <span style="color: #008000;">//<span style="color: #008000;"> 先渲染子节点 然后添加到当前节点
      .each(<span style="color: #0000ff;">this.children,<span style="color: #0000ff;">function<span style="color: #000000;">(child) {
      <span style="color: #0000ff;">var childEl = (child <span style="color: #0000ff;">instanceof Element) ?<span style="color: #000000;"> child.render()
      : document.createTextNode(child)
      el.appendChild(childEl)
      })

      <span style="color: #0000ff;">return<span style="color: #000000;"> el
      }

    module.exports = Element

    diff.js

    _ = require('./util' patch = require('./patch.js' listDiff = require('list-diff2'<span style="color: #008000;">/<span style="color: #008000;">

    • 统计更新前后 DOM 树的改变

    • @param {Element} oldTree 更新前 DOM 树

    • @param {Element} newTree 更新后 DOM 树
      <span style="color: #008000;">/
      <span style="color: #0000ff;">function<span style="color: #000000;"> diff(oldTree,newTree) {
      <span style="color: #0000ff;">var index = 0
      <span style="color: #0000ff;">var patches =<span style="color: #000000;"> {}
      dfsWalk(oldTree,newTree,index,patches)
      <span style="color: #0000ff;">return<span style="color: #000000;"> patches
      }
      <span style="color: #008000;">/
      <span style="color: #008000;">*

    • dfs 遍历新旧 DOM 树

    • patches 记录差异
      <span style="color: #008000;">*/
      <span style="color: #0000ff;">function<span style="color: #000000;"> dfsWalk(oldNode,newNode,patches) {
      <span style="color: #0000ff;">var currentPatch =<span style="color: #000000;"> []

      <span style="color: #0000ff;">if (newNode === <span style="color: #0000ff;">null<span style="color: #000000;">) {
      <span style="color: #008000;">//<span style="color: #008000;"> 如果该节点被删除 不需要做任何事情
      } <span style="color: #0000ff;">else <span style="color: #0000ff;">if (.isString(oldNode) &&<span style="color: #000000;"> .isString(newNode)) {
      <span style="color: #008000;">//<span style="color: #008000;"> 如果改变前后该节点都是文本类型
      <span style="color: #0000ff;">if (newNode !==<span style="color: #000000;"> oldNode) {
      currentPatch.push({ type: patch.TEXT,content: newNode })
      }
      } <span style="color: #0000ff;">else <span style="color: #0000ff;">if (oldNode.tagName === newNode.tagName && oldNode.key ===<span style="color: #000000;"> newNode.key) {
      <span style="color: #008000;">//<span style="color: #008000;"> 当节点的类型以及key都相同的时候 判断两个节点的属性是否有变化
      <span style="color: #0000ff;">var propsPatches =<span style="color: #000000;"> diffProps(oldNode,newNode)
      <span style="color: #0000ff;">if<span style="color: #000000;"> (propsPatches) {
      currentPatch.push({ type: patch.PROPS,props: propsPatches })
      }
      <span style="color: #008000;">//<span style="color: #008000;"> 当新节点包含ignore属性的时候 不比较其子节点
      <span style="color: #008000;">//<span style="color: #008000;"> (也就是说 如果子节树不会有变化的话 手动添加 ignore 属性来防止比较子节点降低效率???
      <span style="color: #0000ff;">if (!<span style="color: #000000;">isIgnoreChildren(newNode)) {
      diffChildren(oldNode.children,newNode.children,patches,currentPatch)
      }
      } <span style="color: #0000ff;">else<span style="color: #000000;"> {
      <span style="color: #008000;">//<span style="color: #008000;"> 节点的类型不同 直接替换
      <span style="color: #000000;"> currentPatch.push({ type: patch.REPLACE,node: newNode })
      }

      <span style="color: #0000ff;">if<span style="color: #000000;"> (currentPatch.length) {
      patches[index] =<span style="color: #000000;"> currentPatch
      }
      }
      <span style="color: #008000;">/<span style="color: #008000;">

    • 比较两个元素的子节点列表

    • @param {Array<Element|String>} oldChildren

    • @param {Array<Element|String>} newChildren
      <span style="color: #008000;">/
      <span style="color: #0000ff;">function<span style="color: #000000;"> diffChildren(oldChildren,newChildren,currentPatch) {
      <span style="color: #008000;">//<span style="color: #008000;"> 此处未实现 diff 算法 直接引用 list-diff2 的 listDiff 函数
      <span style="color: #0000ff;">var diffs = listDiff(oldChildren,'key'<span style="color: #000000;">)
      newChildren =<span style="color: #000000;"> diffs.children
      <span style="color: #008000;">//<span style="color: #008000;"> 如果有移动 就为当前节点标记改变
      <span style="color: #0000ff;">if<span style="color: #000000;"> (diffs.moves.length) {
      <span style="color: #008000;">//<span style="color: #008000;"> diffs.moves 记录节点的移动顺序
      <span style="color: #0000ff;">var reorderPatch =<span style="color: #000000;"> { type: patch.RECORDER,moves: diffs.moves }
      currentPatch.push(recorderPatch)
      }
      <span style="color: #008000;">//<span style="color: #008000;"> leftNode 记录的是前一个子节点 根据dfs遍历的顺序为每个节点标号(index
      <span style="color: #0000ff;">var leftNode = <span style="color: #0000ff;">null
      <span style="color: #0000ff;">var currentNodeIndex =<span style="color: #000000;"> index
      _.each(oldChildren,<span style="color: #0000ff;">function<span style="color: #000000;">(child,i) {
      <span style="color: #008000;">//<span style="color: #008000;"> 对于每一个子节点 进行比较
      <span style="color: #0000ff;">var newChild =<span style="color: #000000;"> newChildren[i]
      currentNodeIndex = (leftNode && leftNode.count) ? currentNodeIndex + leftNode.count + 1<span style="color: #000000;">
      : currentNodeIndex + 1<span style="color: #000000;">
      dfsWalk(child,newChild,currentNodeIndex,patches)
      leftNode =<span style="color: #000000;"> child
      })
      }
      <span style="color: #008000;">/
      <span style="color: #008000;">*

    • 比较新旧节点的属性变化
      <span style="color: #008000;">*/
      <span style="color: #0000ff;">function<span style="color: #000000;"> diffProps(oldNode,newNode) {
      <span style="color: #0000ff;">var count = 0
      <span style="color: #0000ff;">var oldProps =<span style="color: #000000;"> oldNode.props
      <span style="color: #0000ff;">var newProps =<span style="color: #000000;"> newNode.props

      <span style="color: #0000ff;">var<span style="color: #000000;"> key,value
      <span style="color: #0000ff;">var propsPatches =<span style="color: #000000;"> {}
      <span style="color: #008000;">//<span style="color: #008000;"> 记录写与原节点相比 值改变的属性
      <span style="color: #0000ff;">for (key <span style="color: #0000ff;">in<span style="color: #000000;"> oldProps) {
      value =<span style="color: #000000;"> oldProps[key]
      <span style="color: #0000ff;">if (newProps[key] !==<span style="color: #000000;"> value) {
      count++<span style="color: #000000;">
      propsPatches[key] =<span style="color: #000000;"> newProps[key]
      }
      }
      <span style="color: #008000;">//<span style="color: #008000;"> 记录之前不存在的属性
      <span style="color: #0000ff;">for (key <span style="color: #0000ff;">in<span style="color: #000000;"> newProps) {
      value =<span style="color: #000000;"> newProps[key]
      <span style="color: #0000ff;">if (!<span style="color: #000000;">oldProps.hasOwnProperty(key)) {
      count++<span style="color: #000000;">
      propsPatches[key] =<span style="color: #000000;"> newProps[key]
      }
      }
      <span style="color: #008000;">//<span style="color: #008000;"> 改变前后节点属性完全相同 返回 null
      <span style="color: #0000ff;">if (count === 0) <span style="color: #0000ff;">return <span style="color: #0000ff;">null

      <span style="color: #0000ff;">return<span style="color: #000000;"> propsPatches
      }

    <span style="color: #0000ff;">function<span style="color: #000000;"> isIgnoreChildren(node) {
    <span style="color: #0000ff;">return (node.props && node.props.hasOwnProperty('ignore'<span style="color: #000000;">))
    }

    module.exports = diff

    patch.js

    _ = require('./util'<span style="color: #0000ff;">var REPLACE = 0 <span style="color: #008000;">//<span style="color: #008000;"> 替换元素
    <span style="color: #0000ff;">var
    REORDER = 1 <span style="color: #008000;">//<span style="color: #008000;"> 移动 删除 新增 子节点
    <span style="color: #0000ff;">var PROPS = 2 <span style="color: #008000;">//<span style="color: #008000;"> 修改节点属性
    <span style="color: #0000ff;">var TEXT = 3 <span style="color: #008000;">//<span style="color: #008000;"> 修改文本内容<span style="color: #008000;">
    /<span style="color: #008000;">

    • @param {element} node 改变之前的渲染结果

    • @param {Object} patches 通过 diff 计算出的差异集合
      <span style="color: #008000;">/
      <span style="color: #0000ff;">function<span style="color: #000000;"> patch(node,patches) {
      <span style="color: #0000ff;">var walker = { index: 0<span style="color: #000000;"> }
      dfsWalk(node,walker,patches)
      }
      <span style="color: #008000;">/
      <span style="color: #008000;">*

    • dfs 遍历dom树 根据旧节点和patches渲染新节点

    • @param {element} node 更改之前的 dom 元素

    • @param {*} walker 记录走到第几个节点(so...为什么不直接传index...

    • @param {Object} patches 节点之间的差异集合
      <span style="color: #008000;">*/
      <span style="color: #0000ff;">function<span style="color: #000000;"> dfsWalk(node,patches) {
      <span style="color: #0000ff;">var currentPatches =<span style="color: #000000;"> patches[walker.index]

      <span style="color: #0000ff;">var len = node.childNodes ? node.childNodes.length : 0
      <span style="color: #008000;">//<span style="color: #008000;"> 先渲染子节点
      <span style="color: #0000ff;">for (<span style="color: #0000ff;">var i = 0; i < len; i++<span style="color: #000000;">) {
      <span style="color: #0000ff;">var child =<span style="color: #000000;"> node.childNodes[i]
      walker.index++<span style="color: #000000;">
      dfsWalk(child,patches)
      }
      <span style="color: #008000;">//<span style="color: #008000;"> 如果当前节点存在差异 就重新渲染
      <span style="color: #0000ff;">if<span style="color: #000000;"> (currentPatches) {
      applyPatches(node,currentPatches)
      }
      }

    <span style="color: #0000ff;">function<span style="color: #000000;"> applyPatches(node,currentPatches) {
    <span style="color: #008000;">//<span style="color: #008000;"> 根据差异类型的不同 进行不同的渲染
    _.each(currentPatches,<span style="color: #0000ff;">function<span style="color: #000000;">(currentPatch) {
    <span style="color: #0000ff;">switch<span style="color: #000000;"> (currentPatch.type) {
    <span style="color: #0000ff;">case<span style="color: #000000;"> REPLACE:
    <span style="color: #008000;">//<span style="color: #008000;"> 替换 重新创建节点 并替换原节点
    <span style="color: #0000ff;">var newNode = (<span style="color: #0000ff;">typeof currentPatch.node === 'string'<span style="color: #000000;">)
    ?<span style="color: #000000;"> document.createTextNode(currentPatch.node) : currentPatch.node.render()
    node.parentNode.replaceChild(newNode,node)
    <span style="color: #0000ff;">break
    <span style="color: #0000ff;">case<span style="color: #000000;"> REORDER:
    <span style="color: #008000;">//<span style="color: #008000;"> 子节点重新排序
    <span style="color: #000000;"> reorderChildren(node,currentPatch.moves)
    <span style="color: #0000ff;">break
    <span style="color: #0000ff;">case<span style="color: #000000;"> PROPS:
    <span style="color: #008000;">//<span style="color: #008000;"> 重新设置属性
    <span style="color: #000000;"> setProps(node,currentPatch.props)
    <span style="color: #0000ff;">break
    <span style="color: #0000ff;">case<span style="color: #000000;"> TEXT:
    <span style="color: #008000;">//<span style="color: #008000;"> 改变文本值
    <span style="color: #0000ff;">if<span style="color: #000000;"> (node.textContent) {
    node.textContent =<span style="color: #000000;"> currentPatch.content
    } <span style="color: #0000ff;">else<span style="color: #000000;"> {
    <span style="color: #008000;">//<span style="color: #008000;"> IE
    node.nodeValue =<span style="color: #000000;"> currentPatch.content
    }
    <span style="color: #0000ff;">break
    <span style="color: #0000ff;">default<span style="color: #000000;">:
    <span style="color: #0000ff;">throw <span style="color: #0000ff;">new Error('Unknown patch type ' +<span style="color: #000000;"> currentPatch.type)
    }
    })
    }
    <span style="color: #008000;">/<span style="color: #008000;">

    • 为节点重新设置属性 属性值为undefined表示该属性被删除了

    • @param {element} node

    • @param {Object} props
      <span style="color: #008000;">/
      <span style="color: #0000ff;">function<span style="color: #000000;"> setProps(node,props) {
      <span style="color: #0000ff;">for (<span style="color: #0000ff;">var key <span style="color: #0000ff;">in<span style="color: #000000;"> props) {
      <span style="color: #008000;">//<span style="color: #008000;"> 所以到底为什么不使用 undefined
      <span style="color: #008000;">//<span style="color: #008000;"> undefined 并不是保留词(reserved word),它只是全局对象的一个属性,在低版本 IE 中能被重写
      <span style="color: #0000ff;">if (props[key] === <span style="color: #0000ff;">void 0<span style="color: #000000;">) {
      node.removeAttribute(key)
      } <span style="color: #0000ff;">else<span style="color: #000000;"> {
      <span style="color: #0000ff;">var value =<span style="color: #000000;"> props[key]
      _.setAttr(node,value)
      }
      }
      }
      <span style="color: #008000;">/
      <span style="color: #008000;">*

    • 将节点根据moves重新排序

    • @param {element} node DOM元素

    • @param {Obejct} moves diff算法根据新旧子树以及key算出的移动顺序
      <span style="color: #008000;">*/
      <span style="color: #0000ff;">function<span style="color: #000000;"> reorderChildren(node,moves) {
      <span style="color: #0000ff;">var staticNodeList =<span style="color: #000000;"> _.toArray(node.childNodes)
      <span style="color: #0000ff;">var maps =<span style="color: #000000;"> {}

      _.each(staticNodeList,<span style="color: #0000ff;">function<span style="color: #000000;">(node) {
      <span style="color: #008000;">//<span style="color: #008000;"> nodeType 属性返回以数字值返回指定节点的节点类型。
      <span style="color: #008000;">//<span style="color: #008000;"> nodeType === 1 表示 元素element
      <span style="color: #0000ff;">if (node.nodeType === 1<span style="color: #000000;">) {
      <span style="color: #0000ff;">var key = node.getAttribute('key'<span style="color: #000000;">)
      <span style="color: #0000ff;">if<span style="color: #000000;"> (key) {
      maps[key] =<span style="color: #000000;"> node
      }
      }
      })

      _.each(moves,<span style="color: #0000ff;">function<span style="color: #000000;">(move) {
      <span style="color: #0000ff;">var index =<span style="color: #000000;"> move.index
      <span style="color: #0000ff;">if (move.type === 0<span style="color: #000000;">) {
      <span style="color: #008000;">//<span style="color: #008000;"> 删除节点
      <span style="color: #0000ff;">if (staticNodeList[index] ===<span style="color: #000000;"> node.childNodes[index]) {
      node.removeChild(node.childNodes[index])
      }
      <span style="color: #008000;">//<span style="color: #008000;"> splice() 方法可删除从 index 处开始的零个或多个元素,并且用参数列表中声明的一个或多个值来替换那些被删除的元素。
      <span style="color: #008000;">//<span style="color: #008000;"> arrayObject.splice(index,howmany,item1,.....,itemX)
      staticNodeList.splice(index,1<span style="color: #000000;">)
      } <span style="color: #0000ff;">else <span style="color: #0000ff;">if (move.type === 1<span style="color: #000000;">) {
      <span style="color: #008000;">//<span style="color: #008000;"> 新增节点 如果之前就存在相同的key 就将之前的拷贝 否则创建新节点
      <span style="color: #008000;">//<span style="color: #008000;"> cloneNode() 创建节点的拷贝 并返回该副本 参数为true表示深拷贝
      <span style="color: #0000ff;">var insertNode = maps[move.item.key] ? maps[move.item.key].cloneNode(<span style="color: #0000ff;">true<span style="color: #000000;">)
      : ( (<span style="color: #0000ff;">typeof move.item === 'object') ?<span style="color: #000000;"> move.item.render()
      : document.createTextNode(move.item))
      staticNodeList.splice(index,0<span style="color: #000000;">,insertNode)
      node.insertBefore(insertNode,node.childNodes[index] || <span style="color: #0000ff;">null<span style="color: #000000;">)
      }
      })
      }

    patch.REPLACE =<span style="color: #000000;"> REPLACE
    patch.REORDER =<span style="color: #000000;"> REORDER
    patch.PROPS =<span style="color: #000000;"> PROPS
    patch.TEXT =<span style="color: #000000;"> TEXT

    module.exports = patch

    (编辑:李大同)

    【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

      推荐文章
        热点阅读