v-for遍历数组或者对象,渲染结构、v-bind动态设置class和style
·
(一)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>
<!-- item:每个成员(自定义的名字) -->
<!-- index:下标(自定义的名字) -->
<!-- list:被遍历的数据 -->
</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>
<!--item:成员 index:下标 -->
<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(){
// 往list内部添加一个新的成员
let one = {
// 模拟后台数据,id为了数据与数据之间的区分,不一定非得是整数!
id:Math.random(),
name:"新来的",
age:19
};
// 添加到数组的第二个位置
this.list.splice(1,0,one);
// 1:代表从数组下标为1的位置进行操作
// 0:代表不删除的个数为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,那么就有这个类,否则没有这个类。
<template>
<div>
<h1>操作类名</h1>
<!-- 对象用法 -->
<!-- 'aa' 'bb'已经定义好的类名 -->
<!-- key1,key2:值Boolean值,决定前面类名要不要! -->
<div class="box" :class="{'aa':key1,'bb':key2}"></div>
<button @click="key1=!key1">添加aa类名</button>
<button @click="key2=!key2">添加bb类名</button>
</div>
</template>
<script>
export default {
data(){
return{
key1:true,
key2:false,
}
}
}
</script>
<style>
.box{
width: 200px;
height: 200px;
border: 1px solid #000;
}
.aa{
background-color: pink;
}
.bb{
box-shadow: 0 0 10px #000; /* 盒子阴影 */
}
</style>
②、数组:数组中的所有类,都会添加到盒子上。
<template>
<div>
<h1>操作类名</h1>
<!-- 数组用法 -->
<!-- arr:变量,值是一个数组 -->
<!-- 把数组里面成员(类名),全部一次性给了当前盒子 -->
<div class="box" :class="arr"></div>
<button @click="arr=['aa','bb','cc']">添加类名</button>
</div>
</template>
<script>
export default {
data(){
return{
key1:true,
key2:false,
arr:[],
}
}
}
</script>
<style>
.box{
width: 200px;
height: 200px;
border: 1px solid #000;
}
.aa{
background-color: pink;
}
.bb{
box-shadow: 0 0 10px #000; /* 盒子阴影 */
}
</style>
- v-bind对于类名操作的增强,注意点:class不会影响到原来的class属性。
2、用v-bind动态设置标签的style行内样式
- 语法:
:style="对象/数组"
:class="{类名: 布尔值}”, true使用, false不用
:class="[类名1,类名2]”
:style="{css属性名: 值}"
<template>
<div>
<h1>操作类名</h1>
<!-- 对象用法比较多 -->
<!-- width:css属性名 -->
<!-- w:要设置的属性值 -->
<div class="box" :style="{'width':w,'background-color':bgc}"></div>
</div>
</template>
<script>
export default {
data(){
return{
w:"300px",
bgc:"#ccc"
}
}
}
</script>
<style>
.box{
width: 200px;
height: 200px;
border: 1px solid #000;
}
</style>
<template>
<div>
<h1>操作类名</h1>
<!-- 数组用法 -->
<div class="box" :style="arr"></div>
</div>
</template>
<script>
export default {
data(){
return{
w:"300px",
bgc:"#ccc",
arr:[
{
width:"400px",
backgroundColor:"green"
},{
height:"100px"
}
]
}
}
}
</script>
<style>
.box{
width: 200px;
height: 200px;
border: 1px solid #000;
}
</style>
<div class="box" :style="{color:color, backgroundColor: bg }">123</div>
<div class="box" :style="[styleObj1, styleObj2]">123</div>
更多推荐
已为社区贡献8条内容
所有评论(0)