持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第8天,点击查看活动详情
这是根据上一篇虚拟节点的差异化分析 得到的差异化数组,来对真实的dom打补丁的,我们需要定义个函数,把把原始dom和补丁包传进去作处理
index.js
dopatch(realdom,h) // 真实dom h为补丁包
我们新建了一个dopatch.js文件 一步一步看
let oldpatch = {}; // 这个是保存原始补丁的
let realindex =0; // 补丁是有编号的所以真实节点也需要有编号
// 新声明了两个属性
写了dopatch方法
function dopatch(realdom,patch) {
oldpatch = patch
realDomwalk(realdom) // 这方法很重要 这是递归真实dom用的
}
realDomwalk函数
// 真实dom的遍历也是深度优先遍历
function realDomwalk(realdom) {
// 拿到应对应的节点补丁没有·就是空
const rnPatch = oldpatch[realindex++] // 这个是拿到相对应真实dom索引的补丁
// 当前节点可能会有children
const childNodes = realdom.childNodes; // 这个拿到的是类十足
[...childNodes].map(item=>{
// item是子节点
realDomwalk(item) // 相当于真实节点的递归
})
// 判断rnPatch是否存在 如果存在就开始打补丁
if (rnPatch) {
patchAction(realdom,rnPatch) // 这个函数才是真的的打补丁函数 当前节点的补丁
}
}
patchAction这个方法 也是比较重要的这是我们用来做打补丁的方法
function patchAction(realdom,patch) {
// patch应该是补丁包样子 0: [
// {
// type: "ATTR",
// attrs: {
// class: 'llll'
// }
// }
// ],
// 是个数组
patch.forEach(item=>{
// 这里需要判断一下属性
if (item.type==ATTR) { // 如果是attr我们需要为真实dom替换属性
for (let k in item.attrs) {
let value = item.attrs[k]
// 判断value是否存在 如果存在我们就进行打补丁
if (value) {
setAtts(realdom,k,value)
} else {
realdom.removeAttribute(k)
}
}
} else if(item.type==TEXT) { // 如果是文本节点 直接给节点赋值就可以了
realdom.textContent = item.text
} else if (item.type==REPLACE) {
// 如果是替换节点 我们需要先删除节点 在之前的父节点添加节点
// 需要判断一下新的节点是不是符合我们Element构造出来的
// 如果是Element构造出来 需要变为真实dom
// 如果不是就是文本节点
let newNode =(item.newDom instanceof Element)?render(item.newDom): document.createTextNode(item.newDom)
console.log(item)
realdom.parentNode.replaceChild(newNode,realdom)
} else if (item.type==REMOVE) { // 直接删除节点
realdom.parentNode.removeChild(realdom)
}
})
}
代码里的注释其实就是这个这个方法里最重要的,我们写的这个只做个4中操作,其实只是提供了一个大概的思路,复杂操作的思路其实差不多,如果大家想要这个源码的话可以给我留言,感谢阅读