VUE | key的内部原理、Vue监测数据的原理、Vue.set()和vm.$set()的使用
目录
目录
一、react、vue中的key有什么作用?(key的内部原理)
1.虚拟DOM中key的作用:
2.对比规则:
3.用index作为key可能会引发的问题:
4.开发中如何选择key?
5.当index作为key时的原理图:
6.当唯一标识(id)作为key时的原理图:
二、Vue监测数据的原理
三、Vue.set()的使用
一、react、vue中的key有什么作用?(key的内部原理)
1.虚拟DOM中key的作用:
key是虚拟DOM对象的标识,数据发生变化时,VUE会根据【新数据】生成【新的虚拟DOM】,随后VUE进行【新虚拟DOM】与【旧虚拟DOM】的差异比较。
2.对比规则:
- 旧虚拟DOM中找到了与新虚拟DOM相同的key:
- 若虚拟DOM中内容没变,直接使用之前的真实DOM
- 若虚拟DOM中内容变了,则生成新的真实DOM,随后替换页面中之前的真实DOM
- 旧虚拟DOM中未找到与新虚拟DOM相同的key,创建新的真实DOM,随后渲染到页面
3.用index作为key可能会引发的问题:
- 若以数据进行:逆序添加、逆序删除等破坏顺序操作,会产生没有必要的真实DOM更新,界面效果没问题,但效率低
- 如果结构中还包含输入类的DOM,会产生错误DOM更新,界面有问题
4.开发中如何选择key?
- 最好使用每条数据的唯一标识作为key,比如id、手机号、身份证号等唯一值。
- 如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表,用于展示,使用index作为key是没有问题的。
5.当index作为key时的原理图:
6.当唯一标识(id)作为key时的原理图:
二、Vue监测数据的原理
我们之前有在博客中说过,vm中的_data相当于复制了Vue在的data,所以实例对象中会有data中的所有属性,但仅仅是赋值嘛?
其实不是,在赋值之前会对data进行一个简单的加工,使data中的每一个属性都有自己的一个getter、setter。
当改变数据:调用setter --> 然后重新解析模板 --> 生成虚拟DOM --> 对比算法 --> 生成真实DOM --> 重新渲染页面。
三、Vue.set()的使用
我们先来看一下这段代码:
<body>
<div id="root">
<h2>学校:{{name}}</h2>
<h2>地址:{{address}}</h2>
<h2>学生姓名:{{student.studentName}}</h2>
<h2>学生年龄:{{student.studentAge}}</h2>
</div>
<script src="./js/vue.js"></script>
<script>
Vue.config.productionTip = false
const vm = new Vue({
el:'#root',
data:{
name:'尚硅谷',
address:'北京',
student:{
studentName:'tom',
// studentAge:18
}
}
})
</script>
</body>
我们可以看到,我把【学生年龄】这个属性给注掉了,我们的模板还是有{{student.studentAge}}这个变量,可是并没有报错!是因为 【studentAge】并不是data中的属性。
接下来,我们想给它添加【studentAge】这个属性,在不直接操作data的情况下,我们应该怎么办呢?
有的同学可能会觉得,简单,直接【vm._data.student.studentAge = 18】不就可以了嘛!我们来试一下:
可以看到,我们成功给_data添加了这个属性,但是页面并没有这个数据,这是为什么呢?
细心的同学可以看到,我们之前写的【studentName】或者其它之前就写好的属性都有自己的getter和setter,但是我们后面添加的这个属性却没有,没错!这就是导致我们页面没有办法更新数据的原因!!!
难道这就意味着,如果我们后期想要添加数据,就没有办法渲染到页面上了嘛?
当然不是啊,下面我们就来介绍一下Vue.set()这个方法。
Vue.set ( target , key , val )
- target:给谁添加
- key:添加什么属性
- val:添加的属性值是多少
okk,我们现在就用这个办法来实现一下,我们刚刚的想法。
哈哈哈~是不是成功了,我们的【studentAge】也拥有了自己的getter和setter,真是皆大欢喜呐!
除了 Vue.set ( target , key , val ),我们还可以通过 vm.$set(target , key , key )
好啦,我们就不在控制台操作了,给我们之前的代码做一个完善,就是我们今天的ending~
<body>
<div id="root">
<h2>学校:{{name}}</h2>
<h2>地址:{{address}}</h2>
<h2>学生姓名:{{student.studentName}}</h2>
<button @click="addAge">点击添加年龄</button>
<h2 v-if="student.studentAge">学生年龄:{{student.studentAge}}</h2>
<!-- <h2>学生性别:{{student.sex}}</h2> -->
</div>
<script src="./js/vue.js"></script>
<script>
Vue.config.productionTip = false
const vm = new Vue({
el:'#root',
data:{
name:'尚硅谷',
address:'北京',
student:{
studentName:'tom',
// studentAge:18
}
},
methods: {
addAge(){
Vue.set(this.student,'studentAge',19)
}
},
})
</script>
</body>
效果图:
拜比~