Vue基础篇-内置指令
第五章
5.1基本指令
5.1.1 v-cloak
<style>
[v-cloak]{
display: none;
}
</style>
<body>
<div id="app">
<div v-cloak>
{{message}}
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var app = new Vue({
el: '#app',
data() {
return {
message:'解决屏幕闪动'
}
}
})
</script>
</body>
当网速较慢时,加载或者刷新页面的时候回出现{{message}}字样
使用v-cloak可以解决初始化慢导致页面闪动的最佳实践,对于简单的项目很实用。
但是在工程化文件中,项目的html结构只有一个空的div元素
剩下的内容都是由路由挂载不同的组件完成的,所以不再需要v-cloak。
5.1.2 v-once
<body>
<div id="app">
<p v-once>{{msg}}</p>
<p>{{msg}}</p>
<p>
<input type="text" v-model = "msg" name="">
</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var app = new Vue({
el: '#app',
data() {
return {
msg:'解决屏幕闪动'
}
}
})
</script>
</body>
当输入框值改变,即绑定的msg改变,使用了v-once的标签一直都是初始值
不会随着改变。
5.2 条件渲染指令
5.2.1 v-if、v-else-if、v-else
与js的条件渲染语句if、else if、else类似,条件指令决定节点是否渲染上页面。
<body>
<div id="app">
<p v-if="status===1">status为1显示</p>
<p v-else-if="status===2">status为2显示</p>
<p v-else="status===3">status为3显示</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var app = new Vue({
el: '#app',
data() {
return {
status:2
}
}
})
</script>
</body>
示例
<body>
<div id="app">
<template v-if="type==='name'">
<label for="">用户名:</label>
<input type="text" placeholder="请输入用户名">
</template>
<template v-else>
<label for="">邮箱:</label>
<input type="text" placeholder="请输入邮箱">
</template>
<button @click="handler()">切换输入类型</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var app = new Vue({
el: '#app',
data() {
return {
type:'name'
}
},
methods:{
handler(){
this.type=this.type==='name'?'mail':'name';
}
}
})
</script>
</body>
点击切换按钮来回切换姓名和邮箱之间的输入
5.2.2 v-show
v-show和v-if用法基本上一致,但是v-show是改变了css的样式
v-show='false'相当于display:none.
注意一点 v-show不能在template上使用。
两者之间的区别:
v-if是真正意义上的条件渲染,如果条件为假,则一开始就不会渲染节点,适用于不经常切换条件时。
v-show只是简单的css样式的改变,无论条件真假都会渲染。适用于频繁切换条件。
5.3 列表渲染指令v-for
5.3.1 遍历数组
当需要将一个数组遍历或者枚举一个对象循环显示时,就会用到v-for。
<style>
[v-cloak]{
display: none;
}
</style>
<body>
<div id="app">
<ul>
<li v-cloak v-for="(item,index) in items" :key="item.index">{{item.name}}</li>
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var app = new Vue({
el: '#app',
data() {
return {
items:[
{id:1,name:'vue基础'},
{id:2,name:'vue进阶'},
{id:3,name:'vue高阶'},
{id:4,name:'vue实战'},
]
}
},
methods:{
}
})
</script>
</body>
此处也可以用of作为迭代器
<li v-cloak v-for="(item,index) of items" :key="item.index">{{item.name}}</li>
此外,也可以将v-for放在template上但是不能将:key放在template上
这样可以实现多个元素进行渲染。
<style>
[v-cloak]{
display: none;
}
</style>
<body>
<div id="app">
<ul>
<template v-cloak v-for="(item,index) of items">
<li :key="item.index">书名:{{item.name}}</li>
<li :key="item.index">作者:{{item.anthor}}</li>
</template>
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var app = new Vue({
el: '#app',
data() {
return {
items:[
{id:1,name:'vue基础',anthor:'like'},
{id:2,name:'vue进阶',anthor:'lisi'},
{id:3,name:'vue高阶',anthor:'zhangsan'},
{id:4,name:'vue实战',anthor:'lingling'},
]
}
},
methods:{
}
})
</script>
</body>
5.3.2 枚举对象
<style>
[v-cloak]{
display: none;
}
</style>
<body>
<div id="app">
<ul>
<li v-cloak v-for="(value,key,index) in items" :key="index">{{index}}-{{key}}:{{value}}</li>
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var app = new Vue({
el: '#app',
data() {
return {
items:{
name:'like',age:'24',gender:'male'
}
}
},
methods:{
}
})
</script>
</body>
5.3.3 迭代整数
<span v-cloak v-for="n in 10">{{n}}</span>
5.3.4 数组更新
vue的核心就是数据的双向绑定,当我们修改数组时,vue会监测到数据的变化
所以用v-for渲染的视图也会立即更新
vue包含了一些数组的变异方法,使用它们改变数组也会触发视图更新。
1.push()
2.pop()
3.unshift()
4.shiftf()
5.spice()
6.sort()
7.reverse()
不改变原数组的情况
filter()筛选
concat()组合
slice()
以下变动的数组中,vue是不能检测到的,也不会触发视图更新。
通过索引直接设置项,比如app.books[3]={name:'css探索',author:'lea Verou'}
修改数组的长度,比如app.books.length=1
解决第一个问题可以用两种方法实现
第一种是vue的内置set方法
Vue.set(app.books,3,{name:'css探索',author:'lea Verou'})
第二中方法是
app.books。splice(3,1,{name:'css探索',author:'lea Verou'})
5.3.5 过滤与排序
<style>
[v-cloak]{
display: none;
}
</style>
<body>
<div id="app">
<ul>
<li v-cloak v-for="(book,index) in filterbooks" :key="book.index">{{book.name}}</li>
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var app = new Vue({
el: '#app',
data() {
return {
books:[
{name:'html'},
{name:'java'},
{name:'js'},
{name:'vue'}
]
}
},
computed:{
filterbooks(){
return this.books.filter(function(book){
return book.name.match(/js/)
})
}
}
})
</script>
</body>
通过调用filter的方法返回正则匹配后的进行渲染
5.4 修饰符
.stop
.prevent
.capture
.self
.once
<span @click.stop="handler()"></span>
<form @submit.prevent='handle()'></form>
<a @click.stop.prevent="handler()"></a>
<div @click.capture="handler()"></div>
键盘事件
<input @keyup.13='dosomething'>
按下回车触发事件
5.5 购物车开发
5.5.1 index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>shopping car</title>
<link rel="stylesheet" href="./index.css">
</head>
<body>
<div id="app" v-cloak>
<template v-cloak v-if="items.length">
<table>
<thead>
<tr>
<th>商品编号</th>
<th>商品名称</th>
<th>商品单价</th>
<th>购买数量</th>
<th>总价</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="(item,index) in items" :key="item.index">
<td>{{index+1}}</td>
<td>{{item.name}}</td>
<td>{{item.price}}</td>
<td>
<button :disabled='item.count===1' @click="decrease(index)">-</button>
{{item.count}}
<button @click="increase(item)">+</button>
</td>
<td>{{item.count*item.price}}</td>
<td>
<button @click="remove(index)">移除</button>
</td>
</tr>
</tbody>
</table>
<span>总价:{{totalprices}}</span>
</template>
<div v-else>购物车为空</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="./index.js"></script>
</body>
</html>
5.5.2 index.css
table {
text-align: center;
background-color: tomato;
border: 1px solid #e9e9e9;
border-collapse: collapse;
border-spacing: 0;
empty-cells: show;
}
th,td{
padding:8px 16px;
border: 1px solid #e9e9e9;
}
th{
background: #f7f7f7;
color: #5c6b77;
font-weight: 600;
white-space: nowrap;
}
button {
border: none;
outline: none;
border-radius: 20px;
}
5.5.3 index.js
var app = new Vue({
el: "#app",
data() {
return {
items: [
{ id: 1, name: "apple", price: 5555, count: 2 },
{ id: 2, name: "pear", price: 5, count: 2 },
{ id: 3, name: "orange", price: 4, count: 2 },
{ id: 4, name: "apple", price: 5, count: 2 }
]
};
},
methods: {
decrease(index) {
if(this.items[index].count===1) return;
this.items[index].count--;
},
increase(item) {
item.count++;
},
remove(index) {
this.items.splice(index, 1);
}
},
computed:{
totalprices(){
var total=0;
for (let index = 0; index < this.items.length; index++) {
total+=this.items[index].price*this.items[index].count;
}
return total.toString().replace(/\B(?=(\d{3})+$)/g,',')
}
}
});