(一)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个更新
    在这里插入图片描述
③、区别:
  1. 设置和不设置key有什么区别?
    ①、不设置key,默认同级兄弟元素按照下标进行比较。
    ②、设置了key,按照相同key的新旧元素比较。
  2. key值要求是?
    ①、字符串或者数组,唯一不重复。
    ②、有id用id,有唯一值用唯一值,实在没有,才用索引。
  3. 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>
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐