vue2.x之条件渲染和列表渲染

条件渲染

条件渲染,顾名思义,就是根据特定条件渲染内容。在使用条件渲染的时候,我们一般都会使用到两类指令:v-if和v-show

v-if指令

v-if指令的意思就是说当指令的表示式返回的是true,那么就会加载渲染对应的DOM节点,否则就不会加载渲染。

⏰ 基本用法

<div v-if="1 === 1">条件渲染-内容</div>

上面的v-if的表达式返回的是true,所以就会渲染出来。 效果如下:

 

如果上面那个表达式返回的是false, 那么就不会渲染出来。

<div v-if="1 === 2">条件渲染-内容</div>

效果如下:

⏰ 多个v-if可以同时使用

v-if可以定义多个,只要条件满足,都可以渲染出来。

<div v-if="1 === 1">条件渲染-内容1</div>
<div v-if="1 === 2">条件渲染-内容2</div>
<div v-if="1 === 1">条件渲染-内容3</div>

效果如下:

条件为true才会加载对应节点,否则不会加载对应节点 效果如下:

内容2的条件返回的是false,那么只有它不会渲染出来

⏰ 搭配v-else-if, v-else使用

这些指令其实和js中的if -> else-if -> else 是一样的。

<div v-if="1 === 2">条件渲染-内容1</div>
<div v-else-if="1 === 1">条件渲染-内容2</div>
<div v-else-if="1 === 3">条件渲染-内容3</div>
<div v-else>条件渲染-内容4</div>

效果如下:

在搭配这些指令使用的时候不能中断,否则后面的内容是不能加载出来的。

div v-if="1 === 2">条件渲染-内容1</div>
<div>中断文本</div>
<div v-else-if="1 === 1">条件渲染-内容2</div>
<div v-else-if="1 === 3">条件渲染-内容3</div>
<div v-else>条件渲染-内容4</div>

如果v-if,v-else-if这些指令中途中断了,编辑器就会提示错误,页面不能渲染。

⏰ 搭配template使用

我们之前学习tempplate的标签的时候,就知道它的作用主要就是充当一个容器元素,和普通的容器元素(比如div)相比,它不会渲染成真正的DOM节点。

<template v-if="1 === 1">
  <div>条件渲染-内容1</div>
  <div>条件渲染-内容2</div>
  <div>条件渲染-内容3</div>
  <div>条件渲染-内容4</div>
</template>

页面渲染的时候没有渲染出tempalate元素,效果如下:

v-show指令

v-show翻译过来就是显示的意思,也就是无论条件是怎样的,这些DOM节点都会加载,如果返回条件是true的话那就显示出来,相当于是display: inline-block或者display: block,否则就是display:none.

⏰ 基本用法

<div v-show="1 === 2">条件渲染-内容1</div>
<div v-show="1 === 1">条件渲染-内容2</div>

效果如下:

⏰ 多个v-show同时使用

多个v-show和多个v-if一样,也可以使用多个。

<div v-show="1 === 2">条件渲染-内容1</div>
<div v-show="1 === 1">条件渲染-内容2</div>
<div v-show="1 === 1">条件渲染-内容3</div>
<div v-show="1 === 1">条件渲染-内容4</div>

效果如下:

v-if和v-show的区别

1. 通过上面的例子我们也可以看出,v-if是根据条件是否加载对应的DOM节点,而v-show是一定会加载对应的节点,只是根据条件是否显示,相当于是display。

2. 如果项目需求场景中切换频率比较高,建议使用v-show,否则建议使用v-if。

3. 有些时候我们需要控制某个代码块是否渲染,为了不破坏元素的DOM结构,这时候我们可以使用template来充当容器,而且在渲染的时候template是不会渲染成DOM节点的。

4. template上面如果要使用条件渲染指令的话,只能使用v-if,不能使用v-show。

列表渲染

列表渲染其实本质上就是模板内容的循环加载,主要是使用v-for指令来实现的。其中v-for可以在很多主体上,比如,对象,数组等。

v-for的几种方式

⏰ v-for里使用数组

在v-for中使用数组,和js中相同,有item, index,其中item表示数组项, index表示索引。

<div v-for="(item, index) in arr" :key="index">
  {{item}}-{{index}}
</div>

data () {
  return {
    arr: [12, 22, 32, 42, 52, 62]
  }
}

效果如下:

⚠️ 特别注意: (item, index) in arr中的item和index的顺序不能写错。否则模板里面的内容不能正确渲染

⏰ v-for里使用对象

在v-for中使用对象,也有两个关键变量,但是和数组中不同的是,不再是in关键字了,而是of关键字,而且有三个变量是value,key和index, value表示对象的属性值,key表示对象的属性, index表示索引

<div v-for="(value, key, index) of obj" :key="key">
  {{key}}-{{value}}-{{index}}
</div>

data () {
  return {
    obj: {
      name: '张三',
      age: 18,
      sex: 'man'
    }
  }
}

效果如下:

 

⚠️ 特别注意:(value, key) of obj中的value和key的顺序不能写错,否则可能不能正确渲染出来。

⏰ v-for循环固定次数

如果只是想要让某些模板重复渲染几次,那么就可以使用v-for循环固定次数。使用方法是index of num(次数)。

<div v-for="index of 5" :key="index">
  {{index}}
</div>

效果如下:

 

⚠️ 特别注意:这种方法只有一个关键变量index,不能有其他变量。否则浏览器会报错。

⏰ v-for里使用字符串

v-for里不仅可以使用数组,对象,其实也可以使用字符串。

<div v-for="index of 'thastring'" :key="index">
  {{index}}
</div>

效果如下:

⚠️ 特别注意:使用v-for遍历字符串的时候,字符串之间不能有空格,而且字符串的每一项之间不能有重复。由此种种,这种方式基本上不会用到

⏰ 小结

1. 很多时候,后端接口给我们返回动态数据,然后需要按照一定模板格式将这些数据动态加载出来,这时候就需要用到列表渲染了。
2. 列表渲染虽然有好几种用法,但是在实际开发中我们最常用的还是使用数组和对象的方式。

列表渲染中的过滤

上面主要是介绍列表渲染的一些常见的使用方法。这里我们开始介绍一些列表渲染中关于列表数据的处理。 很多时候,我们从后端拿到了很多数据,但是往往在渲染的时候我们并不是要按照接口返回的数据展示,而是要将数据进行处理之后再渲染出来,比如:过滤或者排序。

列表的过滤主要会用到计算属性。

<div v-for="(item, index) in newArr" :key="index">
  {{ item }}-{{ index }}
</div>

data () {
  return {
    arr: [1, 13, 5, 2, 8, 23, 16, 34]
  }
},
computed: {
  newArr () {
    return this.arr.filter(item => item > 1)
  }
},

效果如下:

列表渲染中的排序

排序其实和过滤差不多,也是会用到计算属性,计算属性可以监听到原来数据的变化及时计算并响应出来。

<div v-for="(item, index) in newArr" :key="index">
  {{item}}-{{index}}
</div>

data () {
  return {
    arr: [1, 13, 5, 2, 8, 23, 16, 34]
  }
},
computed: {
  newArr () {
    const arr = this.arr
    arr.sort((a, b) => {
      return a - b
    })
    return arr
  }
}

效果如下:

 

列表渲染中的唯一索引key

我们都知道通常在列表渲染中使用v-for指令时,需要指定唯一索引key,那为什么要指定唯一索引key呢?这就要从DOM Diff说起,由于篇幅原因,这里我们就介绍一下 dom diff的流程,后面我们再从源码角度,深入介绍DOM Diff的实现原理。

⏰ DOM Diff的流程

当我们的数据发生变化的时候,模板也会相应地更新,那么这时候就需要使用DOM Diff, 主要流程如下:

  1. 根据旧的数据生成对应的虚拟DOM(也就是DOM对象)
  2. 如果数据更新了,修改对应的虚拟DOM的数据,生成新的虚拟DOM
  3. 然后比较新旧两个虚拟DOM,这个过程是一层层地去比较,寻找的有变化的部分,根据key渲染到真正的DOM节点上

这样如果没有变化的节点,它的虚拟DOM是没有变化的,这时候就不需要重新渲染DOM,如果需要删除的DOM,就直接根据key删除对应的DOM,这样就能大大提高渲染效率,也能避免由于没有唯一索引导致的渲染错误。

⏰ 使用key时需要注意的地方

  1. 为同一层的相同类型的元素添加key属性 为同一层相同类型的元素添加key值,那么在添加或者删除的时候就可以根据key值直接对DOM进行添加和删除,这样能够大大提高效率
  2. key不能是index下标值 当数组发生增加和删除时,打乱了它的顺序,它的下标是会发生改变的,因此不能保证修改数据前,相同key对应的是同一个DOM。因此在使用key时,建议使用唯一值。
  3. 设置key 如果数组的下标不会发生变化,那么直接使用index即可,如果数组的下标会发生变化,建议使用唯一索引,比如后端接口返回的id或者其他前端的唯一标识属性。如果不设置key值,那么vue会默认将index作为key值。

数组更新检测

这块也是基于vue的数组响应式原理来实现数组的更新的。

⏰ 变更数组

下面这些方法是更新原来的数组,是可以实现视图的即时更新。

<div class="hello">
  <div v-for="(item, index) in arr" :key="index">
    {{item}}-{{index}}
  </div>
  <button @click="updateInfo">更新数组</button>
</div>

data () {
  return {
    arr: [1, 13, 5, 2, 8, 23, 16, 34]
  }
},
methods: {
  updateInfo () {
    // this.arr.push(1)
    // this.arr.pop()
    // this.arr.shift()
    // this.arr.unshift(10)
    // this.arr.splice(0, 1)
    // this.arr.sort()
    // this.arr.reverse()
    this.arr = [1, 2, 3, 4]
  }
}

效果如下

⏰ 数组替换

下面这些方法会重新返回新的数组,相当于原数组是不变的,因此想要让视图更新,必须重新绑定数组。

<div class="hello">
  <div v-for="(item, index) in arr" :key="index">
    {{item}}-{{index}}
  </div>
  <button @click="updateInfo">替换数组</button>
</div>
data () { return { arr: [1, 13, 5, 2, 8, 23, 16, 34] } }, methods: { updateInfo () { // this.arr = this.arr.filter(item => item > 10) // this.arr = this.arr.concat([4, 6, 12, 30]) this.arr = this.arr.slice(0, 1) } }

效果如下

v-for的其他使用

v-for除了上面我们介绍的可以用在标签上,还有一些使用我们也应该要注意。

⏰ v-for用在template上

v-for也是可以使用在template上,因为template也是一个标签,只是它不会渲染成真正的DOM节点。

<template v-for="(item, index) in arr">
  <div :key="index">
    {{item}}-{{index}}
  </div>
</template>

data () {
  return {
    arr: [1, 13, 5, 2, 8, 23, 16, 34]
  }
},

效果如下:

⚠️ 特别注意:在vue2中,如果将v-for用在template上,那么唯一标识key是不能写在template上的。因为template不会渲染成真正DOM,而key需要写在真正DOM上。

⏰ v-for用在组件上

这种方式一般适用于在循环遍历数据,然后将每一项的数据传到对应的组件。

  • parent.vue
    // parent.vue
    <div class="hello">
      <Child v-for="(item, index) in arr" :key="index" :value="item"></Child>
    </div>
    
    components: {
      Child
    },
    data () {
      return {
        arr: [1, 13, 5, 2, 8, 23, 16, 34]
      }
    }
  • child.vue

    // child.vue
    <template>
      <div class="child">
        <span>{{value}}</span>
      </div>
    </template>
    
    <script>
    export default {
      name: 'Child',
      props: {
        value: ''
      },
      data () {
        return {
        }
      }
    }
    </script>

效果如下:

⏰ v-for和v-if同时使用

一般不推荐将v-for和v-if同时使用在同一个元素上,但是在某些时候这样写是可以的,并且可以实现遍历加过滤的效果。

<template v-for="(item, index) in arr" v-if="item > 5">
  <div :key="index">
    {{item}}-{{index}}
  </div>
</template>

效果如下:

⚠️ 从上面的效果我们可以看出,v-for和v-if同时使用的话,v-for的优先级要比v-if高。

posted on 2024-07-09 23:58  梁飞宇  阅读(19)  评论(0)    收藏  举报