真实DOM: 文档对象模型, 是网页中标签在js中的映射对象, 每一个标签都是一个dom元素对象<br /> 虚拟DOM: 通过js对象结构模拟html标签结构的一种数据格式, 他并不是标签元素, 只不过结构和标签元素结构相似而已, 虚拟dom只针对数据对象操作, 与界面视图无关, 故,虚拟dom执行效率比真实dom执行效率高很多
<body>
<script src='https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js'></script>
<div id='myApp'>
vue2.0开始, vue中引入了虚拟dom的概念(抄react), 虚拟dom实质上是使用js对象代替了dom元素结构, 数据更新是遍历dom替换成了遍历js对象, 大大提高了遍历执行的速度和效率, 使页面渲染更新更加高效, 节省内存和性能
<button @click="btnClick">更新</button>
<h1 id="title">{{name}}</h1>
<div id="d1">
<span class="more">更多内容</span>
</div>
</div>
<script>
new Vue({
el: '#myApp',
data: {
name: "张三"
},
methods: {
btnClick(){
// this.name = "李四" // 正常的数据更新
// 虚拟DOM实现步骤3: data数据更新时, 会调用数据底层的set函数
this.nameSet("李四")
},
// 模拟实现name字段的set函数
nameSet(name){
this.name = name
// 虚拟DOM实现步骤4: 在data数据更新之后, 创建一个新的虚拟dom树
this.virtualDOM2 = {
name: "div",
attr: [
{id: "myApp"}
],
children: [
{
name: "button",
events: [
{click: this.btnClick}
],
children: "更新"
},
{
name: "h1",
attr: [
{id: 'title'}
],
children: this.name
},
{
name: "div",
attr: [
{id: 'd1'}
],
children: [
{
name: "span",
attr: [
{class: "more"}
],
children: "更多内容"
}
]
}
]
}
console.log(this.virtualDOM1, this.virtualDOM2)
// 虚拟DOM实现步骤5:拿新的虚拟dom对象和原来的虚拟dom对象做对比, 找出他们之间的最小差异, 把新老虚拟dom树传入一个diff函数内,计算差异, diff函数中有算法(叫diff算法)用于计算dom树差异,也是虚拟dom中的核心算法
// var diffArr = Vue.diff(this.virtualDOM1, this.virtualDOM2) 模拟diff算法的调用
var difArr = [
{
query: "#title",
value: '李四'
}
]
// 虚拟DOM实现步骤5: 遍历最小差异数组, 执行真实dom操作, 针对性的更新数组中涉及到的标签元素, 实现局部刷新
difArr.forEach(item=>{
document.querySelector(item.query).innerText = item.value
})
}
},
created() {
// 虚拟DOM实现步骤1: 在vue对象初始化时, 把vue模板中dom标签结构转换成虚拟dom对象结构
this.virtualDOM1 = {
name: "div",
attr: [
{id: "myApp"}
],
children: [
{
name: "button",
events: [
{click: this.btnClick}
],
children: "更新"
},
{
name: "h1",
attr: [
{id: 'title'}
],
children: this.name
},
{
name: "div",
attr: [
{id: 'd1'}
],
children: [
{
name: "span",
attr: [
{class: "more"}
],
children: "更多内容"
}
]
}
]
}
},
beforeMount() {
// 虚拟DOM实现步骤2: 使用虚拟dom对应的找到动态数据所在的标签把动态数据渲染到视图上
document.getElementById("title").innerText.replace("{{name}}", this.name)
},
})
</script>
</body>