Vue 模板逻辑( 条件渲染 & 列表渲染 )

对于一般的模板引擎来说,除了模板内容,还包括模板逻辑。常用的模板逻辑包括:

  • 条件渲染  v-if( 惰性,控制元素是否渲染到页面 ) /   v-show( 控制元素是否显示,已经渲染到页面了 )
  • 列表( 循环 )渲染 v-for  &  key( 作用:帮助 Vue 区分不同的元素,从而提高一定的性能 )
    • 数组更新检测
    • 显示过滤或排序后的结果

不推荐同时使用 v-if 和 v-for,当 v-if 与 v-for 一起使用时,v-for 具有比 v-if 更高的优先级。


条件渲染

条件渲染,可以简单理解为:在 Vue.js 中,符合条件时,对相应的 HTML 模块进行渲染。


  • v-if   
<h2 v-if="awesome">Vue is awesome!</h2>  // 该模块只有在awesome为true时进行渲染

[ 在组件上使用 v-if ]  v-if 是一个指令,所以它一定是被添加在某一个元素上。

但是,如果想同时控制(切换)多个元素呢?— 可以使用 <template> 元素作为不可见元素进行包裹

// 最终渲染的结果上不会包含template元素,它不可见
<template v-if="ok">
	<h1>Title</h1>
	<p>Paragraph 1</p>
</template>

  • v-else                                                          // 顾名思义,"v-if" 的 else
// HTML
<p v-if="show">Hello</p>  // 渲染
   // 它必须紧跟在带 v-if 或者 v-else-if 的元素的后面,否则它将不会被识别。
<p v-else>World</p>  // 不渲染

// JS
data(){
	return{
		show:true
	}
}
  • v-else-if                        // 顾名思义,v-if的“else-if ”,可以连续使用
// 类似于 v-else,它也必须紧跟在带 v-if 或者 v-else-if 的元素之后。
<div v-if="type === 'A'">A</div>
<div v-else-if="type === 'B'">B</div>
<div v-else-if="type === 'C'">C</div>
<div v-else>Not A/B/C</div>

[ 用 key 管理可服用的元素 ] Vue 总是尽可能高效的渲染元素,因此,它通常复用已有的元素而不是从头开始渲染。

# 代码示例:允许用户在不同的登录方式之间切换
// 切换loginType将不会清除用户已经输入的内容
// 因为两个模板使用了相同的元素,<input> 不会被替换掉,仅仅是替换了它的 placeholder。
<template v-if="logintype == 'username'">
	<label for="">UserName</label>
	<input type="text" placeholder="Enter your UserName">
</template>
<template v-else>
	<label for="">Email</label>
	<input type="text" placeholder="Enter your Email">
</template>

这样会使 Vue 变得更快,但也不总是符合实际需求,So,Vue 提供了一种方式来表达 “这两个元素是完全独立的,不要复用它们” — 只需添加一个具有唯一值的 key属性即可。

<template v-if="show">
	<label for="">UserName</label>
	<input type="text" placeholder="Enter your UserName" :key="username-input">
</template>
<template v-else>
	<label for="">Email</label>  // label元素仍然会被高效地复用,因为它们没有添加 key属性
	<input type="text" placeholder="Enter your Email" :key="email-input">
</template>

[ 拓展:v-if   VS   v-show ] 另一个用于根据条件展示元素的选项是 v-show指令。用法大致一样:

# v-show 原理:通过 display:none 控制元素样式是否显示
<h2 v-show="awesome">Vue is awesome!</h2> 

// 说明:v-show 不支持 template 元素,也不支持 v-else。

v-if 具有惰性,如果初始渲染时条件为假,则什么也不做 — 直到条件第一次变为真时,才会开始渲染条件块。它是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。相比之下,v-show简单得多— 无论初始条件是什么,元素总是会被渲染并保留在DOM中,它只是简单地基于 CSS 切换 display 样式。

一般来说,v-if有更高的切换开销,而 v-show有更高的初始渲染开销。因此,

如果需要非常频繁地切换,则使用 v-show较好;如果在运行时条件很少改变,则使用 v-if较好。


列表渲染

v-for 指令需要以 item in items 形式的特殊语法, items 是源数据数组,而 item 是数组元素迭代的别名。


[ 遍历数组 ]  v-for 通常用于根据一组数组的选项列表进行渲染            // 维护状态 key


// HTML
<ul>
  <li v-for="(item,index) in items" :key="index">{{item.name}}</li>    // 也可以用of替代in作为分隔符 item of items
   // 说明:第一个参数是循环得到的数据选项;第二个参数是当前项的索引。
</ul>
 
// JS
data(){
  return{
    items:[
      {name:'标题1'},
      {name:'标题2'}
    ]
  }
}
  • Template v-for:如同 v-if模板,可以用带有 v-for的 <template>标签来渲染多个元素块
<template v-for="item in items">    // 加入key可能会报错
	<li>{{item.msg}}</li>
	<li>测试内容</li>
</template>
  • 显示过滤或排序后的结果 _ 使用计算属性或方法

如果想要显示一个数组经过过滤或排序后的版本,而不实际变更或重置原始数据,可以使用计算属性:

<template>
  <div class="content">
    <ul>
      <li v-for="n in evenNumbers" :key="n">{{ n }}</li>
    </ul>
  </div>
</template>

<script>
export default {
  data() {
    return {
      numbers: [1, 2, 3, 4, 5],
    };
  },
  computed: {
    evenNumbers() {
      // 偶数
      return this.numbers.filter(function (number) {
        return number % 2 === 0;
      });
    },
  },
};
</script>

在计算属性不适应的情况下,也可以使用一个方法:

// HTML

<ul v-for="set in sets">
  <li v-for="n in even(set)">{{ n }}</li>
</ul>

// JS

data: {
  sets: [[ 1, 2, 3, 4, 5 ], [6, 7, 8, 9, 10]]
},
methods: {
  even: function (numbers) {
    return numbers.filter(function (number) {
      return number % 2 === 0
    })
  }
}

[ 对象迭代 ] 也可以使用 v-for 对一个对象的属性进行迭代。

在遍历对象时,是按 Object.keys()的结果遍历,但不能保证它的结果在不同的 JavaScript 引擎下是一致的。

// HTML	
<div v-for="(value,name,index) in person" :key="index">
	// 参数说明:第一个参数是对象的名,即“键”;第二个参数是对象的值;第三个参数是索引
	{{value}} - {{name}} - {{index}}
</div>

// JS
data(){
	return{
		person:{
			name:'jack',
			sex:'male',
			age:20
		}
		
	}
}

[ 整数迭代 v-for ]  v-for也可以取整数。在这种情况下,它将重复多次模板。

<div>
  <span v-for="n in 10">{{ n }}</span>
</div>