最近看了有关vue3.0的视频 做些笔记
下面的内容都是在看完关于vue3.0的简介视频后自己手动敲完一遍
创建vnode
- 使用一个h函数生成js对象(vnode)
<div id="app"></div>
/*
@params
tag String
props Object || null
childer String || Array
*/
function h(tag, props, children) {
return {
tag,
props,
children
}
}
const vdom = h('div', {
class: 'red'
}, [
h('span', null, 'red')
])
挂载
1 写个挂载的函数吧
// 解析vnode 转换陈对于的元素或文本节点
function mount(vnode, container) {
const el = vnode.el = document.createElement(vnode.tag)
// props
if (vnode.props) {
for (let key in vnode.props) {
const value = vnode.props[key]
el.setAttribute(key, value)
}
}
// children
if (vnode.children) {
if (typeof vnode.children === 'string') {
el.textContent = vnode.children
} else {
console.log(1);
vnode.children.forEach(child => {
mount(child, el)
});
}
}
container.appendChild(el)
}
mount(vdom, document.getElementById('app'))
- 做完这步就已经实现了一部分的效果 来看看效果吧
检查更新
- 检查更新是个比较复杂的就写了一个简单的
function patch(n1, n2) {
// 比较两个标签
if (n1.tag === n2.tag) {
const el = n2.el = n1.el
// props
const oldProps = n1.props || {}
const newProps = n2.props || {}
for (const key in newProps) {
const oldValue = oldProps[key]
const newValue = newProps[key]
if (newValue !== oldValue) {
el.setAttribute(key, newValue)
}
}
for (const key in oldProps) {
if (!(key in newProps)) {
el.removeAttribute(key)
}
}
// children
const oldChildren = n1.children
const newchildren = n2.children
if (typeof newchildren === 'string') {
if (typeof oldChildren === 'string') {
if (newchildren !== oldChildren) {
el.textContent = newchildren
}
} else {
el.textContent = newchildren
}
} else {
if (typeof oldChildren === 'string') {
el.innerHTML = ''
newchildren.forEach(child => {
mount(child, el)
})
} else {
const commonLength = Math.min(oldChildren.length, newchildren.length)
for (let i = 0; i < commonLength; i++) {
patch(oldChildren[i],newchildren[i])
}
if (newchildren.length > oldChildren.length) {
newchildren.slice(oldChildren.length).forEach(child => {
mount(child, el)
})
}else if(newchildren.length < oldChildren.length){
oldChildren.slice(newchildren.length).forEach(child => {
el.removeChild(chils.el)
})
}
}
}
} else {
// replace
// ............
}
}
-
这里只写了元素相同下的一个对比 后续有空自己会去完成替换的内容
-
接下来看看结果
const vdom2 = h('div', { class: 'green' }, [ h('span', null, 'changed') ]) patch(vdom, vdom2)