真实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>