1.需要在mount中定义isMounted记录是否是第一次挂载页面,增加存储老的的vnode的preSubtree
import { effectWatch } from './reactivity/index.js'
import { mountElement,diff } from './renderer/index.js'
export function createApp (rootComponent) {
return {
mount (rootContainer) {
const context = rootComponent.setup()
let isMounted = false
let preSubtree;
effectWatch(() => {
if(!isMounted){
isMounted = true
rootContainer.innerHTML = ''
const subTree = rootComponent.render(context)
console.log(subTree)
mountElement(subTree, rootContainer)
preSubtree = subTree
}else{
const subTree = rootComponent.render(context)
diff(preSubtree,subTree)
preSubtree = subTree
}
)
}
}
}
2.简单实现diff算法
export function diff (n1, n2) {
console.log(n1, n2)
if (n1.tag !== n2.tag) {
n1.el.replaceWith(document.createElement(n2.tag))
} else {
const el = n2.el = n1.el
const { props: newProps } = n2
const { props: oldProps } = n1
if (newProps && oldProps) {
Object.keys(newProps).forEach((key) => {
const newVal = newProps[key]
const oldVal = oldProps[key]
if (newVal !== oldVal) {
el.setAttribute(key, newVal)
}
})
}
if (oldProps) {
Object.keys(oldProps).forEach((key) => {
if (!newProps[key]) {
el.removeAttribute(key)
}
})
}
const { children: newChildren } = n2
const { children: oldChildren } = n1
if(typeof newChildren === 'string'){
if(typeof oldChildren === 'string'){
if(newChildren!==oldChildren){
el.textContent = newChildren
}
}else if(Array.isArray(oldChildren)){
el.textContent = newChildren
}
}else if(Array.isArray(newChildren)){
if(typeof oldChildren ==='string'){
el.innerText = ``
mountElement(n2,el)
}else if(Array.isArray(oldChildren)){
const length = Math.min(newChildren.length,oldChildren.length)
for (let i = 0; i < length; i++) {
const newVnode = newChildren[i];
const oldVnode = oldChildren[i];
diff(oldVnode,newVnode)
}
if(newChildren.length>length){
for (let index = length; index < newChildren.length; index++) {
const newVnode = newChildren[index];
mountElement(newVnode)
}
}
if(oldChildren.length>length){
for (let index = length; index < oldChildren.length; index++) {
const oldVnode = oldChildren[index];
oldVnode.el.parent.removeChild(oldVnode.el)
}
}
}
}
}
}