发现一个好文:《》
文章写得非常详细,仔细看了一遍代码,加了一些注释。其实还有有一些地方看的不是很懂(毕竟我菜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;">
<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
(编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|