[TOC]

我们并不总是希望将所有内容呈现到我们的网页上。 根据特定条件或特定表达式的值,我们可能希望隐藏/显示/附加或分离元素。

_

Vue 指令 在这方面,我们有v-ifv-elsev-else-if来帮助我们。

v-if指令

使用v-if指令的语法如下:

<HTML-tag v-if=”condition or expression that evaluates to true or false”>
  • 如果条件为真/求值为真,则将渲染标签。
<div id="app">
  <p v-if="display">Display evaluates to true</p>
  <button type="button" @click="chageVal"> change value</button>

</div>


<script>
  var app = new Vue({
    el: "#app",
    data: {
      display: true
    },
    methods: {
      chageVal() {
        this.display = !this.display
        return this.display;
      }
    }
  });
</script>
  • 让我们向 Vue 实例的数据对象添加display属性,并为其赋予false值。
  • 点击按钮后,由于display的值现在设置为false,因此不会呈现带有文本“显示求值为真”的<p>标签。
  • display值更改为true将呈现第一个<p>标签的内容。


v-else指令

  • 假设您要在显示为true时显示第一个<p>标签,并在显示结果为false时显示第二个<p>标签。 在这种情况下,我们可以使用v-else指令。 它类似于else块。 ```html

    Display evaluates to true

    You always get to see me :)


- 将`display`设为`true`时,将在`v-if`指令的条件求值为`true`的情况下呈现第一个`<p>`标签。
- 将`display`更改为`false`只会使用`v-else`伪指令呈现第二个`<p>`标签

<br />

**注意:**

- _具有`v-else`指令的 HTML 元素必须紧随具有`v-if`的元素。 否则,`v-else`元素将不会被识别。 _
   - _换句话说,不要在`v-if`元素和`v-else`元素之间添加任何元素。_
- 可以在`<div>`,`<template>`等帮助下将这些指令添加到单个 HTML 元素或元素块中。考虑一种情况,您希望根据条件显示错误消息。 在这种情况下`if-else`块会派上用场。
<a name="98x3jx"></a>
## v-else-if指令

- 它也与`v-if`元素一起使用。 该指令充当“`else-if`”条件。 与其他任何编程语言一样,它可以链接多次。
```html
<div id="app">
  <div>
    <p v-if="value > 10">value > 10</p>
    <p v-else-if="value>0  && value < 10">1~10</p>
    <p v-else="value<=0">value &lt;= 0 </p>
  </div>
  <input v-model="inputNum" placeholder="-100~100"></InputNumber>
<button type="button" @click="chageVal"> change value</button>
<button type="button" @click="chageZero"> 判断输入的范围</button>


</div>



<script>
  var app = new Vue({
    el: "#app",
    data: {
      inputNum: null,
      value: 15,
      display: true
    },
    methods: {
      chageVal() {
        this.display = !this.display
        return this.display;
      },
      chageZero() {
        return this.value = this.inputNum
      }
    }
  });
</script>
  • 让我们向数据对象添加value,inputNum属性,并为其提供数值15。
  • v-ifv-else-ifv-else伪指令添加到三个<p>标签并添加条件。
  • 现在,让我们通过输入的值更改val属性的值,并查看输出如何变化。

注意:

  • v-else相似,带有v-else-if指令的元素必须紧随带有v-ifv-else-if的元素。 否则,将无法识别。



_

v-if和v-show

  • 简单来说,v-if 的初始化较快,但切换代价高;v-show 初始化慢,但切换成本低.
  • 手段:
    • v-if是动态的向DOM树内添加或者删除DOM元素;
    • v-show是通过设置DOM元素的display样式属性控制显隐;
  • 编译过程:
    • v-if切换有一个局部编译/卸载的过程,切换过程中合适地销毁和重建内部的事件监听和子组件;
    • v-show只是简单的基于css切换;
  • 编译条件:
    • v-if是惰性的,如果初始条件为假,则什么也不做;只有在条件第一次变为真时才开始局部编译(编译被缓存?编译被缓存后,然后再切换的时候进行局部卸载);
    • v-show是在任何条件下(首次条件是否为真)都被编译,然后被缓存,而且DOM元素保留;
  • 性能消耗:
    • v-if有更高的切换消耗;
    • v-show有更高的初始渲染消耗;
  • 使用场景:
    • v-if适合运营条件不大可能改变;
    • v-show适合频繁切换。
<div id="app">
  <div>
    <p v-show="value>10">v-show</p>
    <p v-if="value > 10">value > 10</p>
  </div>
  <input v-model="inputNum" placeholder="-100~100" />
  <button type="button" @click="chageZero"> 判断输入的范围</button>

</div>

<script>
  var app = new Vue({
    el: "#app",
    data: {
      inputNum: 15,
      value: 15,
      display: true
    },
    methods: {
      chageVal() {
        this.display = !this.display
        return this.display;
      },
      chageZero() {
        return this.value = this.inputNum
      }
    }
  });
</script>
  • 正常显示

image.png

  • 隐藏: v-if 从DOM中移除了

image.png

遍历数组

我们面临的最常见和最简单的方案是遍历数组的各项并将它们呈现为列表。 我们希望将其显示为网页的无序列表。

  • <ul>是项目列表,<li>做列表项,每一项的符号默认是小黑圆点;
    • ul的type属性有:
      • disc—实心圆(默认)
      • circle—空心圆
      • square—实心方块
  • <ol>是编号列表,<li>做列表项,每一项的符号默认是数字;
    • ol的type属性有:
      • 1—数字(默认)
      • a—小写字母
      • A—大写字母
      • i—小写希腊字母
      • I—大写希腊字母。
  • <li>是 list item 即列表项,但列表有很两种,所以外面得有 <ul> 或者 <ol> 用来区别无序列表(小点点)和有序列表(1,2,3…)。
  • dl就是定义一个列表,_dt_列表的标题,_dd_就是内容,能缩进 ```html
    • {{ greeting }}

> 我们为`v-for`指令使用的_特殊语法_是“`greeting in greetings`”。

- 首先, `greeting` – 建议在我们的情况下使用单数名词,`greeting`,作为数组元素的**别名**反复进行。 这可以是您选择的任何名称,然后可以在我们的代码中使用该名称来寻址每个数组项。
- 其次,作为语法一部分的 – **定界符**`in`。 如果您具有 JavaScript 背景,那么所有这些看起来都应该很熟悉,因为在这里我们将`for in`和`for of`用于迭代目的。 即使使用 Vue,我们也可以使用`of`作为分隔符而不是`in`
```html
<li v-for="greeting of greetings">{{ greeting }}</li>
  • 最后, greetings – 必须与 Vue 实例的data对象中的数组名称完全相同。
  • 在这里,为简单起见,简单插值中使用变量greeting。 但它可以像其他任何属性一样使用.
  • 另一种方法是使用v-text指令。 它将greeting设置为文本内容。

    <ul> <li v-for="greeting in greetings" v-text=greeting></li> </ul>
    
  • 可以通过控制台进行,使用push方法向greetings数组添加一个元素。$vm0.greetings.push("namaste"),页面能够显示新加的元素。

image.png

访问当前数组项的索引

  • 语法与我们之前看到的非常相似,

    <div v-for="(greeting, index) in greetings">{{ index }}. {{ greeting}}</div>
    <!-- 使用of测试通过 -->
    <li v-for="(greeting,index) of greetings">{{index}}:{{ greeting }}</li>
    

    image.png

  • 我们必须引入一个 括号 并指定两个用 逗号 分隔的参数,可以选择它们的名称。

    • 第一个参数是指数组元素 – 在我们的示例中是greeting
    • 第二个参数是可选的,它引用当前正在循环的项目的索引 – 在我们的示例中为index,数据从0开始
    • 顺序是最重要的注意事项。 无论您使用什么名称,第一个始终是数组元素,第二个始终是v-for语法中的索引。 然后可以根据需要将其与代码中的这些名称一起使用。

遍历对象

在我们的应用中,我们处理的对象与数组一样多,还用可能是对象数组。 因此,让我们了解如何迭代对象的各种属性。

  • Vue 实例的data对象添加一个简单的对象。为了遍历对象的键值对,我们可以使用相同的v-for指令。 ```html
    • {{ value }}


![image.png](https://cdn.nlark.com/yuque/0/2020/png/385886/1600928520472-d4bf6b20-1fd6-43fc-9ee4-156da1e26ad0.png#align=left&display=inline&height=177&margin=%5Bobject%20Object%5D&name=image.png&originHeight=177&originWidth=994&size=14008&status=done&style=none&width=994)![image.png](https://cdn.nlark.com/yuque/0/2020/png/385886/1600928520472-d4bf6b20-1fd6-43fc-9ee4-156da1e26ad0.png#align=left&display=inline&height=177&margin=%5Bobject%20Object%5D&name=image.png&originHeight=177&originWidth=994&size=14008&status=done&style=none&width=994)- 访问对象的值非常简单。这种语法与遍历数组值非常相似? 如果我们只想从每个键值对中获取值,那么就足够了。    `<li v-for="value of person">{{ value }}</li>`
   - `value `– 您可以选择任何名称。 使用相同的名称访问每个值。
   - `letters `– 必须与`data`对象中的对象名称相同。


<a name="1wwuA"></a>
### 获得键和值
如果我们想在`v-for`语法中使用多个参数,则必须使用括号。 **顺序**在这里很重要。

- **第一个自变量**将始终是**值**
- **第二个自变量**将是**键**。
```html
<li v-for="(value,key) of person">{{key}}:{{ value }}</li>

image.png

访问键,值和当前索引

  • 第三个自变量可用于获取正在访问键值对的当前指标。
  • 同样,这些论据的顺序很重要。
    • 第一个参数将始终是值,
    • 第二个参数将是键,
    • 第三个参数是当前索引。
  • 参数名称可以一如既往地由我们选择。 不要忘记将所有这些参数括在括号中。
    <li v-for="(value,key,index) of person">{{key}}:{{ value }}:{{index}}</li>
    
    image.png
    注意请注意,这些键值对的显示顺序可能会因浏览器而异。 因为顺序基于Object.keys()的结果,该结果返回对象的所有键。
    _

    遍历对象数组

    假设我们的数据对象中有两个简单对象的数组。 ```html
    • Movie name: {{ movie.name }} and
      Character: {{ movie.character }}


- `movie in movies` – 从`movie`变量中的`movies`数组中获取每个对象
- `movie.name`和`movie.character` – 从当前正在循环的单个对象中分别获取键`name`和`character`的值,并将其保存在“`movie`”变量中。
- 请记住,如果您不想使用点运算符或动态呈现键值对,则可以嵌套另一个`v-for`指令。 当然,您可以在其中嵌套任意数量的`v-for`指令。
```html
<li v-for="movie in movies"> 
  <div v-for="(value, key) in movie"> 
    {{ key }}: {{ value }} 
  </div> 
</li>

image.png

跟踪独特的“键”属性

在处理简单列表时,我们可以像到目前为止讨论的那样使用v-for指令。 但是在处理子组件(我们将在本系列教程的后面部分介绍),更新列表元素等过程中,您可能会遇到一些意外行为。为避免在编码时遇到此类颠簸,始终建议提供唯一值并将其绑定到特殊的key属性,如下所示,

在vue中,vue会尽可能的复用之前已经存在的元素,给元素一个唯一的key,该元素将不会被复用,表示该元素是独立的。

<li v-for="movie in movies" v-bind:key="movie.name">

不建议使用下标作为key

  • 定义对象数组,常用的遍历方式(不推荐) ```html
  • id: {{ list.id }} and
    name: {{ list.name }}


- 在最后一条数据后再加一条数据:这个key的值就是索引,之前的索引没有变化。
- 在中间插入一条数据
```html
<script>
  var app = new Vue({
    el: "#app",
    data: {
      lists:[
        {
          id: 1,
          name: 'test1',
        },
        {
          id: 4,
          name: '我是插队的那条数据',
        },
        {
          id: 2,
          name: 'test2',
        },
        {
          id: 3,
          name: 'test3',
        }
      ]
    },
    methos: {

    }
  });
</script>
  • 此时更新渲染数据,通过index定义的key去进行前后数据的对比,发现
  • 之前的数据

    key: 0  index: 0 name: test1    
    key: 1  index: 1 name: test2
    key: 2  index: 2 name: test3
    
  • 之后的数据

    key: 0  index: 0 name: test1
    key: 1  index: 1 name: 我是插队的那条数据
    key: 2  index: 2 name: test2
    key: 3  index: 3 name: test3
    
  • 通过上面清晰的对比,发现除了第一个数据可以复用之前的之外,另外三条数据都需要重新渲染;

  • 我明明只是插入了一条数据,而我想要的只是新增的那一条数据新渲染出来就行了,怎么三条数据都要重新渲染?
    • key的作用主要是为了高效的更新虚拟DOM。另外vue中在使用相同标签名元素的过渡切换时,也会使用到key属性,其目的也是为了让vue可以区分它们,否则vue只会替换其内部属性而不会触发过渡效果。
  • 最好的办法是使用数组中不会变化的那一项作为key值,对应到项目中,即每条数据都有一个唯一的id,来标识这条数据的唯一性;使用id作为key值,我们再来对比一下向中间插入一条数据,此时会怎么去渲染

    <li v-for="(list,index) in lists" v-bind:key="list.id">
    <strong>id:</strong> {{ list.id }} and <br />
    <strong>name:</strong> {{ list.name }}<br />
    </li>
    
  • 之后的数据

    key: 1  id: 1 index: 0  name: test1
    key: 4  id: 4 index: 1  name: 我是插队的那条数据
    key: 2  id: 2 index: 2  name: test2
    key: 3  id: 3 index: 3  name: test3
    
  • 现在对比发现只有一条数据变化了,就是id为4的那条数据,因此只要新渲染这一条数据就可以了,其他都是就复用之前的;

遍历一个范围

  • 如果遇到仅打印从 1 到某些固定整数的数字的情况,那么可以使用Vue 的v-for指令。

    <li v-for="num in 5">{{num}}</li>
    <!-- of语法测试正常 -->
    <span v-for="num of 3">{{num}}</span>
    
  • num – 您选择的任何变量名称,它将在给定范围内循环时代表当前数字

  • in – 分隔符(根据语法)
  • 3 – 范围,表示循环时要考虑的最后一个数字。
  • 假设我们要打印 5次 1 到 3 之间的数字。 按照上面的示例很容易,外部v-for跟踪<div>标签内的代码重复的次数,内部v-for生成 1 到 3 的整数范围。
    <div v-for="number in 5"> 
    <strong>{{ number }}. </strong> 
    <span v-for="num in 3"> {{ num }} </span> &nbsp; 
    </div>