参考:《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>
其中,key
和index
是可选参数,分别表示属性名和索引。
难道,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
两种方式解决第一个问题:
- 使用Vue内置的set方法
Vue.set(app.books,3,{
name:'《css揭秘》',
author:'名字不打了'
});
- 如果在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>