(一)v-for数组变化(增加一项,删除一项), 会更新页面吗?那么数组改变后,是如何更新的呢?
1. v-for
作用:可以遍历数组 或者对象 ,用于渲染结构。 遍历数组语法: ⚫ v-for="item in 数组名"
⚫ v-for="(item, index) in 数组名“
遍历对象语法: ⚫v-for = "(value , key) in 对象名"
遍历数字语法: ⚫v-for = "item in 数字"
key值: ①、不写:默认按照下标给虚拟dom打标识。 ②、index:按照下标给虚拟dom打标识index!就地复用dom节点效率会低。 ③、id:按照下标给虚拟dom打标识id!就地复用dom节点效率会高!
< template>
< div>
< h1> v-for</ h1>
< p> 获取图书列表:[{id:1,name:"zs",age:18},{id:2,name:"ls",age:18}]</ p>
< p> 数组:直接使用v-for 循环!直接写在标签上即可,让那个标签循环,就写在那个标签上</ p>
< ul>
< li v-for = " (item,index) in list" :key = " index" >
姓名:{{ item.name }} 年龄:{{ item.age }}
</ li>
</ ul>
</ div>
</ template>
< script>
export default {
data ( ) {
return {
list : [
{ id : 1 , name : "张三" , age : 18 } ,
{ id : 2 , name : "李四" , age : 66 } ,
{ id : 3 , name : "王五" , age : 99 } ,
]
}
}
}
</ script>
< style>
li {
background-color : #ccc;
font-size : 20px;
}
</ style>
(1)vue的就地复用策略
就地复用:Vue会尽可能的就地(同等级,同位置)复用旧dom结构,对比虚拟dom,进行差异化更新。(效率更高) 下面的就使用到了就地复用 原则,数据变了,页面dom节点留下来,更新为新的dom节点!
< template>
< div>
< h1> v-for</ h1>
< button @click = " add" > 新增一个成员</ button>
< ul>
< li v-for = " (item,index) in list" :key = " index" >
姓名:{{ item.name }} 年龄:{{ item.age }}
</ li>
</ ul>
< hr>
< ul>
< li v-for = " item in list" :key = " item.id" >
姓名:{{ item.name }} 年龄:{{ item.age }}
</ li>
</ ul>
</ div>
</ template>
< script>
export default {
data ( ) {
return {
list : [
{ id : 1 , name : "张三" , age : 18 } ,
{ id : 2 , name : "李四" , age : 66 } ,
{ id : 3 , name : "王五" , age : 99 } ,
]
}
} ,
methods : {
add ( ) {
let one = {
id : Math. random ( ) ,
name : "新来的" ,
age : 19
} ;
this . list. splice ( 1 , 0 , one) ;
}
}
}
</ script>
< style>
li {
background-color : #ccc;
font-size : 20px;
}
</ style>
(2)页面dom结构是一个树形结构
html渲染出来的真是dom树,是个树形结构(复杂) 。每个标签都是树的某个节点。
(3)为什么不对比真实dom节点?每个小真实dom节点很复杂
console.dir(dom)
以文件的形式展开,但是里面非常复杂。每个标签 ,虽然只是树形结构的一个小节点,但属性也非常多。 => 遍历真是dom找差异,非常费时。 真实DOM属性过多,有很多无用的属性,无需遍历对比。 如何优化呢?对比属性少的虚拟dom!
(4)虚拟dom是什么?
虚拟dom:本质就是保存节点信息,描述真实dom的JS对象。(真实DOM在Vue这个电子档案)
< template>
< div id = " box" >
< p class = " my_p" > 123</ p>
</ div>
</ template>
const dom = {
type : 'div' ,
attributes : [ { id : 'box' } ] ,
children : [ {
type : 'p' ,
attributes : [ { class : 'my_p' } ] ,
text : '123'
} ]
}
虚拟dom(一个个js对象):可以用最少的属性结构,描述真实的dom。
(5)虚拟dom对比更新
内存中创建虚拟dom,快速比较变化,给真实DOM打补丁(更新)。
(6)diff算法
但是就算是虚拟dom,和真实dom一样,也是树形结构 内部又是如何对比的呢?
①、策略1:先同层级根元素比较。
如果根元素变化,那么不考虑复用,整个dom树删除重建。 如果根元素不变,对比出属性的变化更新,并考虑往下递归复用。
②、策略2:对比同级兄弟元素
默认按照下标进行对比复用。(:key=“index” 或者 不设置) 就是上面图片显示的1个不动,3个更新 key设置值唯一固定且不变。(:key=“item.id”) 就是上面图片显示的3个不动,1个更新
③、区别:
设置和不设置key有什么区别? ①、不设置key,默认同级兄弟元素按照下标进行比较。 ②、设置了key,按照相同key的新旧元素比较。 key值要求是? ①、字符串或者数组,唯一不重复。 ②、有id用id,有唯一值用唯一值,实在没有,才用索引。 key的好处? key的作用:提高虚拟DOM的对比复用性能。
(二)控制样式,要么操作类,要么操作行内样式,在Vue中,应该如何操作class类呢?如何操作style行内样式呢?
(1)v-bind对于class和style的增强:动态设置class和style
1、用v-bind动态设置标签的class类名
语法::class="对象/数组"
①、对象:如果键值对的值为true,那么就有这个类,否则没有这个类。 ②、数组:数组中的所有类,都会添加到盒子上。 v-bind对于类名操作的增强,注意点:class不会影响到原来的class属性。
2、用v-bind动态设置标签的style行内样式
: class = "{ 类名 : 布尔值} ”, true 使用, false 不用
: class = "[ 类名1 ,类名2 ] ”
: style= "{css属性名: 值}"
< div class = " box" :style = " {color:color, backgroundColor: bg }" > 123</ div>
< div class = " box" :style = " [styleObj1, styleObj2]" > 123</ div>