1.0vue基础 v-for更新监测
目标:当v-for遍历的目标结构改变,vue触发v-for的更新
情况1:数组翻转, 情况2:数组截取 情况3.更新值
口诀:
数组变更方法,就会导致v-for,页面更新
数组非变更方法,返回新数组,就会导致v-for更新,可采用覆盖数组或this.$set()
<template>
<div>
<ul>
<li v-for="(val,index) in arr" :key="index">
{{val}}
</li>
</ul>
<button @click="revBtn">数组翻转</button>
<button @click="sliceBtn">截取前3个</button>
<button @click="updateBtn">更新第一个元素值</button>
</div>
</template>
<script>
export default {
data(){
return {
arr: [5, 3, 9, 2, 1]
}
},
methods:{
revBtn() {
//1.数组翻转可以让v-for更新
this.arr.reverse()
},
sliceBtn() {
//2.数组slice方法不会造成v-for更新
// slice 不会改变原始数组
// this.arr.slice(0,3)
//解决v-for更新 - 覆盖原始数组
let newArr = this.arr.slice(0,3)
this.arr = newArr
},
updateBtn() {
//3.更新莫个值的时候 , v-for是监测不到的
//this.arr[0] = 1000;
//解决=this.$set()
//参数1.更新目标结构
//参数2:更新位置
//参数3:更新值
this.$set(this.arr,0,1000)
}
}
}
</script>
<style>
</style>
这些方法会触发数组改变,v-for会监测到并更新页面
-
push()
-
pop()
-
shift()
-
unshift()
-
splice()
-
sort()
-
reverse()
这些方法不会触发v-for更新
-
slice()
-
filter()
-
concat()
注意,vue不能监测到数组里赋值的动作而更新,如果需要请使用vue.set(),或者this.$set(),或者覆盖整个数组
总结:改变原数组的方法才能让v-for更新
1.1_vue基础_v-for就地更新
v-for的默认行为会尝试原地修改元素而不是移动它们
这种 虚拟DOM对比方式,可以提高性能 - 但是还不够高
1.2_vue基础_虚拟dom
目标:了解虚拟DOM的概念
.vue文件中的template里写的标签,都是模板,都要被vue处理成虚拟DOM对象,才会渲染显示到真实
DOM页面上
1.页面中生成一样的虚拟DOM结构(==本质是一个js对象==)
因为真实的DOM属性好几百,没办法快速的知道那个属性改变了
比如template里标签结构
<template>
<div id="box">
<p class="my_p">123</p>
</div>
</template>
对应的虚拟DOM结构
const dom = {
type: 'div',
attributes: [{id: 'box'}],
children: {
type: 'p',
attributes: [{class: 'my_p'}],
text: '123'
}
}
2.以后vue数据更新
01生成新的虚拟DOM结构
02和旧的虚拟DOM结构对比
03利用diff算法,找不同,只更新变化的部分(重绘/回流)到页面-也叫打补丁
==好处1:提高更新DOM的性能(不用把页面全删除重新渲染)==
==好处2:虚拟DOM只包括必要的属性(没有真实DOM上百个属性)==
总结:虚拟DOM保存在内存中,只记录dom关键信息,配合diff算法提高DOM更新的性能
在内存中比较差异,然后给真实DOM打补丁更新上
1.3_vue基础_diff算法
vue用diff算法,新虚拟dom,和旧的虚拟dom比较
情况1,根元素变了,删除重建
旧虚拟DOM
<div id="box">
<p class="my_p">123</p>
</div>
新虚拟DOM
<ul id="box">
<li class="my_p">123</li>
</ul>
情况2: 根元素没变, 属性改变, ==元素复用==, 更新属性
旧虚拟DOM
<div id="box">
<p class="my_p">123</p>
</div>
新虚拟DOM
<div id="myBox" title="标题">
<p class="my_p">123</p>
</div>
1.4_vue基础_diff算法-key
情况3: 根元素没变, 子元素没变, 元素内容改变
无key - 就地更新
v-for不会移动DOM,而是尝试复用,就地更新,如果需要v-for移动DOM,需要用特殊,attribute key来提供一个排序提示
<ul id="myUL">
<li v-for="str in arr">
{{ str }}
<input type="text">
</li>
</ul>
<button @click="addFn">下标为1的位置新增一个</button>
export default {
data(){
return {
arr: ["老大", "新来的", "老二", "老三"]
}
},
methods: {
addFn(){
this.arr.splice(1, 0, '新来的')
}
}
};
==性能不高,从第二个li往后都更新了==
有key-值为索引
还是就地更新
因为新旧虚拟DOM对比,key存在就复用此标签更新内容,如果不存在就直接建立一个新的
<ul id="myUL">
<li v-for="(str, index) in arr" :key="index">
{{ str }}
<input type="text">
</li>
</ul>
<button @click="addFn">下标为1的位置新增一个</button>
export default {
data(){
return {
arr: ["老大", "新来的", "老二", "老三"]
}
},
methods: {
addFn(){
this.arr.splice(1, 0, '新来的')
}
}
};
1.v-for先循环产生新的DOM结构,key是连接的,和数据对应
2.然后比较新旧DOM结构,找到区别,打补丁到页面上
最后补一个li 然后从第二个往后,都要更新内容
口诀:key的值有id就用id,没有id用索引
有key - 值为id
key的值只能是唯一不重复的,字符串或数值
v-for不会移动DOM,而是尝试复用,就地更新,如果需要v-for移动DOM,你需要用特殊attribute key 来提供一个排序提示
新DOM里的数据的key存在,去旧的虚拟DOM结构里面找到key标记的标签,复用标签
新DOM里数据的key存在,去旧的虚拟DOM结构里没有找到key标签的标签,创建旧的DOM结构的key,在新的DOM结构里没有了,则==移除key所以的标签==
<template>
<div>
<ul>
<li v-for="obj in arr" :key ="obj.id">
{{obj.name}}
<input type="text" >
</li>
</ul>
<button @click="btn">下标1位置插入新来的</button>
</div>
</template>
<script>
export default {
data() {
return {
arr: [
{
name: '老大',
id: 50
},
{
name: '老二',
id: 31
},
{
name: '老三',
id: 10
}
],
}
},
methods:{
btn() {
this.arr.splice(1,0,{
id:19,
name:'新来的'
})
}
}
}
</script>
<style>
</style>
总结:不用key也不影响功能(就地更新),添加key可以提高更新的性能
1.5_阶段小结
v-for什么时候会更新页面呢?
.数组采用更新方法,才导致v-for更新页面
vue是如何提高更新性能的?
.采用虚拟DOM+diff算法提高更新性能
虚拟DOM是什么?
.本质是保存dom关键信息的JS对象
diff算法如何比较新旧虚拟DOM
.根元素改变-删除当前DOM树重新键
.根元素未变,属性改变-更新属性
.根元素未变,子元素/内容改变
.无key-就地更新/有key-按key比较
1.6_vue基础 动态class
目标:用v-bind给标签class设置动态设置
语法:class="{类名:布尔值}"
<template>
<div>
<!-- 语法:
:class="{类名: 布尔值}"
使用场景: vue变量控制标签是否应该有类名
-->
<p :class="{red_str: bool}">动态class</p>
</div>
</template>
<script>
export default {
data(){
return {
bool: true
}
}
}
</script>
<style scoped>
.red_str{
color: red;
}
</style>
总结:就是把类名保存在vue变量中赋予给标签
1.7_vue基础-动态style
目标:标签动态设置style的值
语法:
style:"{css属性:值}"
<template>
<div>
<!-- 动态style语法
:style="{css属性名: 值}"
-->
<p :style="{backgroundColor: colorStr}">动态style</p>
</div>
</template>
<script>
export default {
data(){
return {
colorStr: 'red'
}
}
}
</script>
<style>
</style>
总结:动态style的key都是css属性名