一、更新监测和key
1.1 v-for更新监测
目标:目标结构变化, 触发v-for的更新
情况1: 数组翻转
情况2: 数组截取
情况3: 更新值
<template>
<div>
<ul>
<li v-for="(item, index) in arr" :key="index">{{ item }}</li>
</ul>
<button @click="reverseArr">翻转数组</button>
<button @click="sliceArr">截取数组的前三个元素</button>
<button @click="updateArr">更新第一个元素数组的值</button>
</div>
</template>
<script>
export default {
data () {
return {
arr: [1, 2, 3, 4, 5, 6, 7]
}
},
methods: {
reverseArr () {
// reverse()方法反转数组中元素的位置,改变了数组,并返回该数组的引用。
this.arr.reverse()
},
// slice() 方法返回一个新的数组对象
sliceArr () {
// 因为返回的是一个新的数组,所以不会造成 v-for 的更新,如果要让 v-for 更新,需要从新给原数组覆盖原数组
this.arr = this.arr.slice(0, 3)
},
updateArr () {
this.arr[0] = 100 //没有让页面原数组的值进行了更新 v-for 检测不到更新
// 解决方法
this.$set(this.arr, 0, 100)
}
}
}
</script>
口诀:
数组变更方法, 就会导致v-for更新, 页面更新(返回原数组)
![](https://i-blog.csdnimg.cn/blog_migrate/ce68b0bac5c861a63d32211d45de43c4.png)
数组非变更方法, 返回新数组, 就不会导致v-for更新, 可采用覆盖数组或this.$set()
![](https://i-blog.csdnimg.cn/blog_migrate/b4c4bc6ec765eae112841ffe6c9eaf58.png)
1. 哪些数组方法会导致v-for更新页面?
可以改变原数组的方法
2. 有的数组方法不导致v-for更新页面, 如何处理?
拿返回的新数组, 直接替换旧数组
this.$set()方法更新某个值
1.2 v-for就地更新
目标:当数组改变后是如何更新的
![](https://i-blog.csdnimg.cn/blog_migrate/8dfa5d00b170419022e37f03eb10ab13.png)
v-for更新时,是如何操作DOM的?
循环出新的虚拟 DOM 结构, 和旧的虚拟 DOM 结构对比, 尝试复用标签就地更新内容
1.3 真实DOM
在document对象上, 渲染到浏览器上显示的标签
![](https://i-blog.csdnimg.cn/blog_migrate/655952b1cfb567c11e25401dc96805ff.png)
1.4 虚拟DOM
本质是保存节点信息, 属性和内容的一个JS对象
![](https://i-blog.csdnimg.cn/blog_migrate/c9ee78d4b3db145804ddfe9579bd755b.png)
![](https://i-blog.csdnimg.cn/blog_migrate/9cb740cb1dccc2ce60d63d066a4a577d.png)
在内存中比较变化部分, 然后给真实DOM打补丁(更新)
![](https://i-blog.csdnimg.cn/blog_migrate/0000d67b6adf90ae49fbe835c35bd2e7.png)
1. 虚拟 DOM 是什么?
本质就是一个 JS 对象,保存 DOM 关键信息
2. 虚拟 DOM 好处?
提高 DOM 更新的性能, 不频繁操作真实 DOM,在内存中找到变化部分,再更新真实 DOM (打补丁)
1.5 diff算法
同级比较-根元素变化-整个dom树删除重建
![](https://i-blog.csdnimg.cn/blog_migrate/035c4ac544a99c0fcabfcdc84aa7ce05.png)
同级比较-根元素不变-属性改变更新属性
![](https://i-blog.csdnimg.cn/blog_migrate/65cfc11e10924aae620016b416c99254.png)
1. diff算法如何比较新旧虚拟DOM?
同级比较
2. 根元素变化?
删除重新建立整个DOM树
3. 根元素未变, 属性改变?
DOM复用, 只更新属性
1.6 无key
从第二个往后更新内容 – 性能不高
![](https://i-blog.csdnimg.cn/blog_migrate/20b00d4f53fb0558b5902aecdfb79161.png)
![](https://i-blog.csdnimg.cn/blog_migrate/3d9441dec029d496535f1fe643d27fff.png)
最大限度尝试就地修改/复用相同类型元素
![](https://i-blog.csdnimg.cn/blog_migrate/bd700a7495a299b31e9bc9a8650078d5.png)
1.7 有key, 值为索引
有key属性, 基于key的来比较新旧虚拟DOM, 移除key不存在元素
先产生新旧虚拟DOM, 根据key比较, 还是
就地更新
![](https://i-blog.csdnimg.cn/blog_migrate/c642f907fbb69eca10c5a97812b7fddb.png)
1.8 有key, 值唯一不重复的字符串或数字
有key
属性, 基于key的来比较新旧虚拟DOM, 移除key不存在元素
给每个数据换成对象, 准备id, 把id的值作为key
![](https://i-blog.csdnimg.cn/blog_migrate/c4d20033c55c01cc82f87bff687f6f48.png)
1.9 有key, 值为id
先产生新旧虚拟DOM, 根据key比较
![](https://i-blog.csdnimg.cn/blog_migrate/fa53870e4defe7fb3d0bae011a8d44c0.png)
1. 子元素或者内容改变会分 diff 哪2种情况比较?
无key, 就地更新
有key, 按照key比较
2. key值要求是?
唯一不重复的字符串或者数值
3. key应该怎么用?
有id用id, 无id用索引
4. key的好处?
可以配合虚拟DOM提高更新的性能
1.10 总结
v-for什么时候会更新页面呢?
数组采用更新方法, 才导致v-for更新页面
vue是如何提高更新性能的?
采用虚拟 DOM + diff 算法提高更新性能
虚拟 DOM 是什么?
本质是保存 dom 关键信息的 JS 对象
diff 算法如何比较新旧虚拟 DOM?
根元素改变 – 删除当前 DOM 树重新建
根元素未变, 属性改变 – 更新属性
根元素未变, 子元素/内容改变
无key – 就地更新 / 有key – 按key比较
二、 动态class
用v-bind给标签class设置动态的值
语法 :
class="{类名: 布尔值}"
![](https://i-blog.csdnimg.cn/blog_migrate/0f5d481852c28d86649c3b81c40399d1.png)
![](https://i-blog.csdnimg.cn/blog_migrate/a526d6d4e6effe61e8d40cddac9c3b19.png)
如何给标签class属性动态赋值?
:class=“{类名: 布尔值}”, true使用, false不用
三、 动态style
目标: 给标签动态设置style的值
语法 :
style="{css属性名: 值}"
![](https://i-blog.csdnimg.cn/blog_migrate/ea2f456f6296eee6043c2f0315cfe7e3.png)
给style赋值和class区别是?
:class="{类名: 布尔值}”, true使用, false不用
:style="{css属性名: 值}"
四、数组方法补充
indexOf()
方法返回数组中第一次出现给定元素的下标,如果不存在则返回 -1。
findIndex() 方法返回数组中满足提供的测试函数的第一个元素的索引。若没有找到对应元素则返回 -1。
let arr = [1, 23, 34, 55, 100]
console.log(arr.indexOf(55))
// 找到返回数组下标索引,找不到返回 -1
console.log(arr.findIndex(item => item === 55))