虚拟DOM就是用一个普通的JS对象,用虚拟DOM模拟一个真实的DOM的结构,然后通过对应的方法,创建出真实的DOM,最终插入到页面上
diff算法(差异比较):
修改后的虚拟DOM进行差异比较,快速的将虚拟DOM需要需要修改的地方进行修改,然后在创建出真实的DOM加入到页面上。
用一个普通的JS对象模拟一个DOM对象优点:
在修改DOM时,可以把所有的操作都在虚拟DOM上进行,最终修改完成后,通过createDOM函数,创建出真实的DOM,再次渲染到页面上(节省DOM的操作次数)
难点:要想办法,把虚拟DOM转成真实DOM
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!--
DOM
type 标签 document.createElement('标签名')
props 属性
children 子元素(文本 元素) 插入的父节点.appendChild(子节点)
text 文本节点 document.createTextNode("节点内容")
attributes: 获取当前元素节点上的所有属性节点
-->
<script>
// 生成一个Element类
class Element {
constructor (type, props, children) {
this.type = type
this.props = props
this.children = children
}
}
// 创建工厂函数,调用返回对应的对象
function createElement (type, props, children) {
return new Element(type, props, children)
}
// 创建真实节点
function createNode (vnode) {
// 创建真实的DOM对象
let node = ''
if (typeof vnode === 'string') {
node = document.createTextNode(vnode)
} else {
node = document.createElement(vnode.type)
Object.keys(vnode.props).forEach(key => {
node.setAttribute(key, vnode.props[key])
})
}
return node
}
// console.log(createNode('文本'))
// console.log(createNode(createElement('p', {}, [])))
// 创建真实DOM结构
function createDOM (element) {
// 获取根节点
const root = createNode(element)
if (element.children) {
element.children.forEach(vnode => {
// 递归操作,实现对应的子元素的渲染
root.appendChild(createDOM(vnode))
})
}
return root
}
const vnode = createElement('div', {
x: 1,
class: 'box'
}, ["这是DIV的内容", createElement('p', {class: 'p'}, ['p标签的内容', createElement('input', {
type: 'text',
value: '111'
})])])
document.body.appendChild(createDOM(vnode))
// console.log(vnode)
</script>
</body>
</html>