用到的工具函数(下面用到的时候可以回来看)
export default {
// 判断是否为一个vnode对象
isVnode(b) {
return b.sel === '' || b.sel === undefined
},
// 判断虚拟节点是否为同一个虚拟节点
sameNode(node, node2) {
return node.sel === node2.sel && node.key === node2.key
},
}
vnode 函数生成
/**
* @description:用来生成虚拟dom对象
* @param {*} sel 需要生成的dom
* @param {*} data 标签的属性,点击事件等
* @param {*} children 子级节点
* @param {*} text 子级节点 具有文本对象,children就是空的
* @param {*} elm 虚拟dom生成的真实dom对象
* @return {*} 返回一个vnode 对象
*/
export default function (sel, data, children, text, elm) {
const key = data && data.key ? data.key : ''
return { sel, data, children, text, elm, key }
}
h 函数的实现(增加了一些参数的判断,从而达到参数占位符)
h 函数就是配合 vnode 对象返回一个 vnode 对象
import vnode from './vnode.js'
import is from '../utils/is'
/**
* @description:
* @param {*} sel 需要生成的dom
* @param {*} b dom的属性 key 等
* @param {*} c 子级节点
* @return {*}
*/
export default function (sel, b, c) {
let children
let text
let data
// 判断是c是否为空值 如果为c存在 b肯定就存在
if (c !== undefined) {
// 如果b是真值 直接赋值给data
if (b !== null) {
data = b
}
if (is.array(c)) {
children = c
} else if (is.primitive(c)) {
text = c
} else if (c && c.sel) {
children = [c]
}
// c没有传进来 b有可能是children 也有可能是data
} else if (b !== undefined && b !== null) {
if (is.array(b)) { // 数组类型 为children
children = b
} else if (is.primitive(b)) { //普通类型数据
text = b
} else if (b && b.sel) { // 如果 b为一个 对象并且 sel存在 直接当做children 证明他和vnode函数返回的数据一样
children = [b]
} else { //以上都不满足的情况下 可以判定为 data属性
console.log('b==>', b)
data = b
}
// 静态文本类型 为children
}
// 最后开始判断是否传入了 children属性
if (children !== undefined) {
children.forEach((item, index) => {
if (is.primitive(item)) {
children[index] = vnode(undefined, undefined, undefined, item, undefined)
}
})
}
return vnode(sel, data, children, text, undefined)
}
patch 函数(这里的情况只包1)
- newVnode 存在text属性 oldVnode 没有text属性
- newVnode 没有text 属性 oldVnode 有text属性 xx xx
import is from '../utils/is'
import vnode from '../core/vnode'
export default function patch(oldVnode, newVnode) {
// 把root节点格式化为一个虚拟节点对象
if (is.isVnode(oldVnode)) {
oldVnode = vnode(undefined, undefined, undefined, undefined, oldVnode)
}
if (is.sameNode(oldVnode, newVnode)) {
// 如果是同一个虚拟节点对象 先不管
} else {
// 若果存在文本内容
if (newVnode.text) {
if (newVnode.text != oldVnode.text) {
oldVnode.elm.innerText = newVnode.text
}
}else{
oldVnode.elm.innerText =''
}
}
}
创建一个 index 文件
import h from '../core/h'
import patch from '../core/patch'
const vnode = h('div', 'test')
patch(document.querySelector('.container'), vnode)
到现在我们已经可以生成一个真实节点了