Vue.js实战——内置指令(一)

参考:《Vue.js实战》梁灏

1. 基本指令

1.1 v-cloak

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>v-cloak</title>
		<script src="js/vue.min.js" type="text/javascript" charset="utf-8"></script>
		<style type="text/css">
			[v-cloak] {
				display: none;
			}
		</style>
	</head>
	
	<body>
		<div id="app" v-cloak>
			{{ message }}
		</div>
		<script type="text/javascript">
			var app = new Vue({
				el:"#app",
				data:{
					message:"这是一段文本"
				}
			});
		</script>
	</body>
</html>

单纯使用v-cloak其实作用甚微,当网速较慢,Vue.js文件还没加载完时,页面上还是会出现{{ message }}字样,直到Vue创建实例、编译模板时,DOM才会被替换,所以这个过程屏幕是有闪动的,只要如下加一句CSS就可以了:

[v-cloak] {
				display: none;
			}

1.2 v-once

作用是定义它的元素或组件只渲染一次,包括元素或组件的所有子节点。首次渲染后,不再随数据的变化重新渲染,将被视为静态内容。

2 条件渲染指令

2.1 v-if、v-else-if、v-else

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>条件渲染指令</title>
		<script src="js/vue.min.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		<div id="app">
			<p v-if="status === 1">当status为1时显示该行</p>
			<p v-else-if="status === 2">当status为2时显示该行</p>
			<p v-else>否则显示该行</p>
		</div>
		
		<script type="text/javascript">
			var app = new Vue({
				el:"#app",
				data:{
					status:1
				}
			});
		</script>
	</body>
</html>

v-else-if要紧跟v-if,v-else要紧跟v-else-if或v-if,如果一次判断的是多个元素,可以使用Vue.js内置的template元素上使用条件指令。

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>条件渲染指令</title>
		<script src="js/vue.min.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		<div id="app">
			 <template v-if="status === 1">
				 <p>第一段文本</p>
				 <p>第二段文本</p>
				 <p>第三段文本</p>
			 </template>
		</div>
		
		<script type="text/javascript">
			var app = new Vue({
				el:"#app",
				data:{
					status:1
				}
			});
		</script>
	</body>
</html>

Vue在渲染元素时,处于效率考虑,会尽可能地复用已有的元素而非重新渲染:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>Vue复用元素</title>
		<script src="js/vue.min.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		<div id="app">
			<template v-if="type === 'name'">
				<label>用户名:</label>
				<input type="text" placeholder="输入用户名">
			</template>
			<template v-else>
				<lable>邮箱:</lable>
				<input type="text" placeholder="输入邮箱">
			</template>
			
		<button @click="handleToggleClick">切换输入类型</button>
		</div>
		
		<script type="text/javascript">
			var app = new Vue({
				el:"#app",
				data:{
					type:'name'
				},
				methods:{
					handleToggleClick:function(){
						this.type = this.type === 'name' ? 'mail' : 'name';
					}
				}
			});
		</script>
	</body>
</html>

若想避免上述情况,请使用Vue.js提供的key属性:

			<div id="app">
				<template v-if="type === 'name'">
					<label>用户名:</label>
					<!--   key=“name-input”   -->
					<input type="text" placeholder="输入用户名" key=“name-input”>
				</template>
				<template v-else>
					<lable>邮箱:</lable>
					<!--   key=“email-input”   -->
					<input type="text" placeholder="输入邮箱" key="email-input">
				</template>
				
			<button @click="handleToggleClick">切换输入类型</button>
			</div>

2.2 v-show

v-show用于改变元素的css属性的display,该指令不能在template上使用

<div id="#app">
 	<p v-show="status === 1">当status为1时显示该行</p>
</div>

<script>
var app = new Vue({
	el:"#app",
	data:{
		status:2
	}
});
</script>
<!--渲染后的结果为-->
<p style="display:none">当status为1时显示该行</p>

2.3 v-if与v-show的选择

  • v-if是真正的条件渲染,它会根据表达式适当地销毁或重建元素及绑定的事件或子组件。若表达式初始值为false,则一开始元素/组件并不会渲染,只有当第一次条件为真时才开始编译。
  • v-show只是简单的css属性切换。无论如何,都会被编译。v-if更适合条件不经常改变的场景,因为其切换开销相对较大,而v-show适用于频繁切换条件。

3 列表渲染指令v-for

3.1 基本用法

先来个例子再说:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>v-for初探</title>
		<script src="js/vue.min.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		<div id="app">
			<ul>
				<li v-for="book in books">
					{{ book.name }}
				</li>
			</ul>
		</div>
		
		<script type="text/javascript">
			var app = new Vue({
				el:"#app",
				data:{
					books:[
						{
							name:"Vue.js实战",
							author:"梁灏"
						},
						{
							name:"JavaScript实战",
							author:"未名"
						}
					]
				}
			});
		</script>
	</body>
</html>

输出结果:

  • Vue.js实战
  • JavaScript实战

上例中的 in 也可以用 of来代替

其实,v-for也是可以带索引的,^_^

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>v-for带索引</title>
		<script src="js/vue.min.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		<div id="app">
			<ul>
				<li v-for="(book,index) in books">
					{{index}} _ {{ book.name }}
				</li>
			</ul>
		</div>
		
		<script type="text/javascript">
			var app = new Vue({
				el:"#app",
				data:{
					books:[
						{
							name:"Vue.js实战",
							author:"梁灏"
						},
						{
							name:"JavaScript实战",
							author:"未名"
						}
					]
				}
			});
		</script>
	</body>
</html>

v-for还可以作用在内置标签template上,就像下面这样哈哈哈的写法:

<div id="#app">
<ul>
<template v-for=" book in books ">
<li>{{ book.author }}</li>
<li>{{ book.name }}</li>
</template>
<ul>
</div>

你猜猜,v-for能不能遍历对象?

<!DOCTYPE html>
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>v-for遍历对象</title>
		<script src="js/vue.min.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		<div id="app">
			<span v-for="(value,key,index) in user">{{ index }}_{{ key }}:{{ value }}<br/></span>
		</div>
		
		<script type="text/javascript">
			var app = new Vue({
				el:"#app",
				data:{
					user:{
						name:"Aran",
						age:"呵呵",
						gender:"难"
					}
				}
			});
		</script>
	</body>
</html>

其中,keyindex是可选参数,分别表示属性名和索引。

难道,v-for还可以迭代整数?

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>v-for迭代整数</title>
		<script src="js/vue.min.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		<div id="app">
			<span v-for="n in 10"> {{ n }} </span>
		</div>
		
		<script type="text/javascript">
			var app = new Vue({
				el:"#app"
			});
		</script>
	</body>
</html>

3.2 数组更新

变异方法改变数据会触发视图更新:

  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverse()

非变异方法不会改变原数组:

  • filter()
  • concat()
  • slice()

使用非变异方法时,可以用新数组来替换原数组:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>v-for数组更新</title>
		<script src="js/vue.min.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		<div id="app">
			<ul>
				<li v-for="(book,index) in books">
					{{index}} _ {{ book.name }}
				</li>
			</ul>
		</div>
		
		<script type="text/javascript">
			var app = new Vue({
				el:"#app",
				data:{
					books:[
						{
							name:"Vue.js实战",
							author:"梁灏"
						},
						{
							name:"JavaScript实战",
							author:"未名"
						}
					]
				}
			});
			//这句话应该是重点
			app.books = app.books.filter(function(item){
				return item.name.match(/JavaScript/);
			})
		</script>
	</body>
</html>

Vue在检测数组变化时,并不是直接重新渲染整个列表,而是最大化地复用DOM元素。替换的数组中,含有相同元素的项不会被重新渲染。所以不用担心性能问题。

然而,以下变动的数组中,Vue是不能检测到的,也不会触发视图更新:

  • 通过索引直接设置项,如app.books[3] = {...}
  • 修改数组长度,比如app.books.length=1

两种方式解决第一个问题:

  1. 使用Vue内置的set方法
	Vue.set(app.books,3,{
		name:'《css揭秘》',
		author:'名字不打了'
	});
  1. 如果在webpack中使用组件化的方式,默认没有导入Vue,可以使用$set:
	this.$set(app.books,3,{
		name:'《css揭秘》',
		author:'就不打'
	})
	//这里的this指向的就是当前的组件实例,即app.在非webpack模式下也可以使用$set方法:
	app.books.splice(3,1,{
		name:'《css揭秘》',
		author:'还是不打'
	});

第二个问题可以直接用splice解决:

app.books.splice(1);

3.3 过滤与排序

可以用计算属性,在不改变原数组的情况下,返回过滤或排序后的数组:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>v-for数组更新</title>
		<script src="js/vue.min.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		<div id="app">
			<ul>
				<li v-for="(book,index) in sortBooks">
					{{index}} _ {{ book.name }}
				</li>
			</ul>
		</div>
		
		<script type="text/javascript">
			var app = new Vue({
				el:"#app",
				data:{
					books:[
						{
							name:"Vue.js实战",
							author:"梁灏"
						},
						{
							name:"JavaScript实战",
							author:"未名"
						}
					]
				},
				computed:{
					filterBooks(){
						return this.books.filter(function(book){
							return book.name.match(/JavaScript/);
						})	
					},
					sortBooks(){
						return this.books.sort(function(a,b){
							return a.name.length - b.name.length;
						});
					}
				}
			});
		 
		</script>
	</body>
</html>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值