数据驱动
数据驱动是Vue的核心思想,在Vue中我们只需要通过操作数据来操作DOM(视图),什么意思呢?例如我们需要更改一个文本。
在原生JS中
<p id="title">你好<p>
<script>
let p1 = document.getElementById('title')
p1.innerText = 'hello'
</script>
在Vue中
<p id="app">{{text}}</p>
<script>
let vm = new App({
el: '#app',
data:{
text:'你好'
}
})
vm.text = 'hello'
</script>
在原生JS中我们需要先获取到DOM,然后对DOM进行操作从而改变文本,但是在Vue中,我们只需要对数据进行修改就能更改对应的DOM,我们并不需要直接操作DOM就能够实现对视图的修改。这就是Vue最核心的思想,视图(DOM)和数据是绑定的,通过操作数据就能够操作DOM。
虚拟DOM
这是因为在Vue中,DOM和数据之间有映射关系,而这映射就是通过虚拟DOM来实现的,可以将虚拟DOM理解成一个真实DOM的描述对象,即虚拟DOM就是个对象,用于表示一个真实DOM结构的数据。 Vue会将模板编译然后创建虚拟DOM,这样我们通过操作数据(虚拟DOM)就能够完成对真实DOM的修改。那虚拟DOM只是个JS数据,需要通过Vue把这个虚拟DOM渲染成一个真实的DOM。
下图就是Vue创建的虚拟DOM,也就是用一个对象来表示一个DOM结构
render函数
render函数是用于将数据生成对应的虚拟DOM的。 当我们修改数据后,Vue会重新生成虚拟DOM,然后完成DOM的更新,我们可以通过render函数去验证这点。 render函数用于创建虚拟DOM的,当我们修改数据后这个render函数会重新执行一次,也就是会再次生产一个虚拟DOM。
<div id="app" ref="root"></div>
<script>
var app = new Vue({
el: '#app',
data: {
text:'hello'
},
render:function(h){
var vdom = h('div',{domProps:{innerHTML:this.text}})
console.log('渲染函数执行了')
return vdom
}
})
app.text="你好"
</script>
看浏览器控制台:
说明当我们修改数据后,Vue会重新生产虚拟DOM,然后根据这个虚拟DOM对真实DOM进行更新。
DOM异步更新
现在已经知道了,在Vue中,我们是通过操作数据(虚拟DOM)从而实现对DOM的操作的。这就意味着我们如果更改了数据,对应的DOM应该就会跟着改变。但需要注意的是:DOM的更新是异步的,这就意味着,并不是你修改了数据,其对应的真实的DOM就会立马完成更新。
Vue的官方文档是这样说的:
可能你还没有注意到,Vue 在更新 DOM 时是异步执行的。只要侦听到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更。例如,当你设置 vm.someData = 'new value',该组件不会立即重新渲染。
可以通过代码验证:
<div id="app{{ text }}</div>
<script>
var vm = new Vue({
el: '#',
data: {
text: '我是旧值'
}
})
vm.text = '我是新值' // 更改了数据
console.log(vm.$el.textContent) // 打印值: 我是旧值
</script>
虽然数据已经修改了,但修改后立刻访问DOM,仍是旧值。也代表着我们获取的不是最新的DOM,如何才能在DOM完成更新后操作DOM呢?这就需要使用到Vue提供的API,即Vue.nextTick。
Vue.nextTick
这个是Vue提供的API,它可以在DOM更新完毕之后执行一个回调。也就是说这个API能够检测DOM是否完成了更新,然后在DOM更新后执行回调。
<div id="app">{{ text }}</div>
<script>
var vm = new Vue({
el: '#app,
data: {
text: '我是旧值'
}
})
vm.text = '我是新值' // 更改了数据
Vue.nextTick(function(){
console.log(vm.$el.textContent) //打印值: 我是新值
})
</script>
所以,官网也说过,mounted不会保证所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以在 mounted 内部使用 vm.$nextTick。 至于,nextTick的原理,它到底是如何检测DOM完成更新的,下次文章再分析。