天天看点

Vue 基础自查——条件渲染和列表渲染

  1. v-if

    v-show

    的区别是什么?
  2. v-if

    v-for

    为什么不能一起用?
  3. v-for

    中的

    key

    有什么作用?

1 v-if 和 v-show

1.1 作用

都用来控制元素的显示和隐藏

1.2 控制元素显隐的方式

v-if

控制虚拟

DOM

树上元素的创建和销毁,

Vue

的响应系统会根据虚拟

DOM

树对实际

DOM

进行更新,从而间接控制实际

DOM

上元素的显隐

v-show

通过给元素添加样式

display:none

来让元素隐藏

1.3 初始渲染对比

v-if

是惰性的,如果初始渲染条件为

false

,什么都不做;只有条件为

true

,才会开始编译

v-show

不管初始渲染条件如何,元素始终被编译并保留,之后根据条件通过

CSS

切换

1.4 切换消耗对比

如果频繁切换显示与隐藏,

v-if

会频繁创建、销毁元素,而

v-show

只是切换样式

v-if

的切换消耗更高

1.5 使用场景对比

如果元素的显示隐藏在一开始就定下来不会再变了,使用

v-if

如果元素需要频繁切换显隐,使用

v-show

1.6 其他

  • v-if

    可以搭配

    template

    使用,

    v-show

    不可以
  • v-if

    v-else

    v-show

    无特殊语法

2 v-if 和 v-for

2.1 v-if 和 v-for 不能同时用的原因

为什么不能把

v-if

v-for

同时用在同一个元素上?

当 Vue 处理指令的时候,

v-for

的优先级比

v-if

高,因此这个模板:

<ul>
  <li v-for="item in list" v-if="item.isActive" :key="item.id">
    {{item.name}}
  </li>
</ul>
           

会经过如下运算:

this.list.map(function(item) {
  if (item.isActive) {
    return item.name
  }
})
           

我们每次重新渲染的时候都要遍历整个列表,即使

isActive

true

item

很少,这会带来性能方面的极大浪费,因此两者不能同时用在同一个元素上

2.2 v-if 和 v-for 一起用的解决方案

1、如果想控制整个列表的显隐,可以将

v-if

移动到容器元素上,比如:

<body>
  <div id="example">
    <ul v-if="listShow">
      <li v-for="item in activeItems" :key="item.id">{{item.name}}</li>
    </ul>
  </div>
</body>
<script>
  const vm = new Vue({
    el: "#example",
    data: {
      list: [
        { id: 1, name: "路飞", isActive: true },
        { id: 2, name: "索隆", isActive: false },
        { id: 3, name: "山治", isActive: true },
      ],
      listShow: false,
    }
  });
</script>
           

2、如果想过滤列表中的项目,可以使用计算属性(

computed

)返回过滤后的列表,比如:

<body>
  <div id="example">
    <ul>
      <li v-for="item in activeItems" :key="item.id">{{item.name}}</li>
    </ul>
  </div>
</body>
<script>
  const vm = new Vue({
    el: "#example",
    data: {
      list: [
        { id: 1, name: "路飞", isActive: true },
        { id: 2, name: "索隆", isActive: false },
        { id: 3, name: "山治", isActive: true },
      ],
    },
    computed: {
      activeItems: function () {
        return this.list.filter((item) => item.isActive);
      },
    },
  });
</script>
           

3 列表渲染的 key 有什么用

在使用

v-for

进行列表渲染时,必须给元素添加一个

key

属性,并且这个

key

必须是唯一标识

<ul>
	<li v-for="item in list" :key="item.id">{{item.name}}</li>
</ul>
           

我们知道,Vue 在更新元素时,不会直接操作真实DOM(渲染真实DOM开销是很大的),而是根据新数据生成新的虚拟 DOM,然后对新旧虚拟DOM进行差异对比,根据对比结果进行DOM操作来更新视图

列表渲染时,如果有

key

属性,由于它是唯一标识,在对比两个新旧节点时若

key

不同也就没有深入对比的必要了。

为什么不能用

index

作为

key

?因为

index

是不稳定可变的,比如删除了列表第一个元素,会导致后面的元素

index

发生变化,从而导致

key

发生变化。这时,Vue 在对比新旧节点时,遇到

key

相同的节点,就会进行深入对比,发现节点内容发生了变化,就会去创建新的真实DOM用来替换原来的真实DOM。原本只需要删除真实DOM中第一个元素的操作,会变成新建、替换后续所有真实DOM,造成性能的极大浪费