vue的指令
1.vue 的指令
1.1 指令的概念与分类
指令 是 vue 为开发者提供的模板语法,用于辅助开发者渲染页面的基本结构。
vue 中的指令按照不同的用途可以分为:
- 内容渲染指令
- 属性绑定指令
- 事件绑定指令
- 双向绑定指令
- 条件渲染指令
- 列表渲染指令
1.2 内容渲染指令
内容渲染指令用来辅助开发者渲染 DOM 元素的文本内容。
-
v-text
缺点:会覆盖元素内部原有的内容
<body> <div id="app"> <p v-text="username"></p> <p v-text="gender">性别</p> </div> <!-- 1.导入 vue 的库文件 --> <script src="./lib/vue.js"></script> <!-- 2.创建 vue 实例对象 --> <script> const vm = new Vue({ el: '#app', data: { username: '李四', gender: '男' } }) </script> </body>
-
{{ }}:插值表达式,将对应的值渲染到元素的内容节点
<div id="app"> <p>姓名:{{ username }}</p> <p>性别: {{ gender }}</p> </div>
-
v-html
把包含 HTML 标签的字符串渲染为页面的 HTML 元素
<body> <div id="app"> <p v-html="info"></p> </div> <!-- 1.导入 vue 的库文件 --> <script src="./lib/vue.js"></script> <!-- 2.创建 vue 实例对象 --> <script> const vm = new Vue({ el: '#app', data: { info: '<h4 style="color:red; font-weight:bold">Hello Vue !</h4>' } }) </script> </body
1.3 属性绑定指令
-
插值表达式只能用在元素的内容节点中,不能用在元素的属性节点中!
-
v-bind
可以为元素的属性动态绑定属性值 -
vue 规定
v-bind:
指令可以简写成:
实例代码:
<body>
<div id="app">
<input type="text" name="" id="" v-bind:placeholder="tips">
<img v-bind:src="photo" alt="" style="width: 30px;">
</div>
<!-- 1.导入 vue 的库文件 -->
<script src="./lib/vue.js"></script>
<!-- 2.创建 vue 实例对象 -->
<script>
const vm = new Vue({
el: '#app',
data: {
tips: '请输入用户名',
photo: 'https://cn.vuejs.org/images/logo.svg'
}
})
</script>
</body>
使用 Javascript 表达式:
<body>
<div id="app">
<div>1 + 2 = {{ 1 + 2}}</div>
<div>{{ tips }} 反转 :{{ tips.split('').reverse().join('')}}</div>
<div :title="'box' + index">这是一个 div</div>
</div>
<!-- 1.导入 vue 的库文件 -->
<script src="./lib/vue.js"></script>
<!-- 2.创建 vue 实例对象 -->
<script>
const vm = new Vue({
el: '#app',
data: {
tips: '请输入用户名',
index: 3
}
})
</script>
</body>
1.4 事件绑定指令
1.4.1 如何绑定
vue 提供了 v-on 事件绑定指令,用来辅助程序员为 DOM 元素绑定事件监听。
-
v-on: 事件类型="事件处理函数"
-
触发事件时,
this === vm
-
在绑定事件处理函数时,可以使用
()
传递参数 -
v-on:
可以简写为@
,如@click="xxx"
案例代码:
<body>
<div id="app">
<p>count : {{ count }}</p>
<button v-on:click="add(2)"> + 2 </button>
<button v-on:click="sub"> - 1 </button>
</div>
<!-- 1.导入 vue 的库文件 -->
<script src="./lib/vue.js"></script>
<!-- 2.创建 vue 实例对象 -->
<script>
const vm = new Vue({
el: '#app',
data: {
count: 5
},
// methods 定义事件的处理函数
methods: {
add( n ) {
// this === vm
this.count += n
},
sub() {
this.count --
}
}
})
</script>
</body>
1.4.2 事件对象
- vue 提供内置变量
$event
,是原生的 DOM 的事件对象 e.target
指向触发事件的 DOM 对象
<body>
<div id="app">
<!-- 偶数背景颜色变红 -->
<p>count : {{ count }}</p>
<button v-on:click="add(1 , $event)"> + N </button>
</div>
<!-- 1.导入 vue 的库文件 -->
<script src="./lib/vue.js"></script>
<!-- 2.创建 vue 实例对象 -->
<script>
const vm = new Vue({
el: '#app',
data: {
count: 5
},
// methods 定义事件的处理函数
methods: {
add( n ,e ) {
// this === vm
this.count += n
if(this.count % 2 === 0){
e.target.style.backgroundColor = 'red'
}else{
e.target.style.backgroundColor = ''
}
}
}
})
</script>
</body>
1.4.3 事件修饰符
-
取消事件的默认行为:
.prevent
原生:
e.preventDefault()
<div id="app"> <a href="http://www.baidu.com" @click.prevent="show">跳转到百度首页</a> </div>
-
阻止时事件冒泡:
.stop
原生:
e.stopPropagation()
如果子元素和父元素同时绑定 click 事件,那么点击子元素,会先触发子元素的点击事件然后再往外冒泡,触发父元素的点击事件。
-
以捕获模式触发当前的事件处理函数:
.Capture
-
绑定的事件只能触发一次:
.once
-
只有在 event.target 是当前元素自身时触发事件处理函数:
.selt
1.4.4按键修饰符
在监听键盘事件时,我们经常需要判断详细的按键。此时,可以为键盘相关的事件添加按键修饰符。
-
<input type="text" @keyup.esc="clearInput">
当
key
是Esc
时调用clearInput
-
<input type="text" @keyup.enter="submit">
当
key
是Enter
时调用submit
例子:
<body>
<div id="app">
<input type="text" @keyup.esc="clearInput">
</div>
<!-- 1.导入 vue 的库文件 -->
<script src="./lib/vue.js"></script>
<!-- 2.创建 vue 实例对象 -->
<script>
const vm = new Vue({
el: '#app',
data: {
count: 5
},
// methods 定义事件的处理函数
methods: {
clearInput(e) {
console.log('触发了 clearInput')
e.target.value = ''
}
}
})
</script>
</body>
1.5 双向绑定指令
1.5.1 基本使用
vue 提供
v-model
双向数据绑定指令,用来辅助开发在不操作 DOM 的前提下,快速获取表单的数据。
input
文本框中的内容与v-model
指令绑定的数据一致- 当操作
input
文本框内容v-model
指令绑定的数据也会一起改变 v-model
能和 input 输入框(type=radio,checkbox,xxx),textarea,select 一起使用
<body>
<div id="app">
<div id="app">
<p>用户的名字是:{{ username }} </p>
<input type="text" v-model="username" >
<hr>
<input type="text" :value="username" >
<hr>
<select v-model="city">
<option value="">请选择城市</option>
<option value="1">北京</option>
<option value="2">上海</option>
<option value="3">广州</option>
</select>
<!-- 没有意义 -->
<div v-model="username"></div>
</div>
<script src="./lib/vue.js"></script>
<script>
// 创建 vue 实例对象
const vm = new Vue({
el: '#app',
data: {
username: 'ZhangSan'
}
})
</script>
</body>
1.5.2 v-model 指令的修饰符
为了方便对用户输入的内容进行处理
修饰符 | 作用 | 实例 |
---|---|---|
.number | 自动把输入值转为Number 类型 | <input type="text" v-model.number="n1"> |
.trim | 去掉首尾空白字符 | <input type="text" v-model.trim="username"> |
.lazy | 在change 时而非input 时更新 | <input type="text" v-model.lazy="username"> |
.trim
只会取出首端和末尾的空格,中间的不会取出.lazy
之后在最后输入框失去焦点时同步最后一次数据,中间的变化不会实时同步
<body>
<!-- 希望 vue 能控制下面的这个 div 帮我们把数据填充到 div 内部 -->
<div id="app">
<input type="text" v-model.number="n1"> + <input type="text" v-model.number="n2"> = <span>{{ n1 + n2 }} </span>
<hr>
<input type="text" v-model.trim="username">
<button @click="showName"> 获取用户名 </button>
<hr>
<input type="text" v-model.lazy="username">
</div>
<script src="./lib/vue.js"></script>
<script>
const vm = new Vue({
el: '#app',
data: {
n1: 1,
n2: 2,
username: 'zhangsan'
},
methods: {
showName() {
console.log(`用户名是:"${this.username}"`)
}
}
})
</script>
</body>
1.6 条件渲染指令
1.6.1 v-if 和 v-show
条件渲染指令用来辅助开发者按需控制 DOM 的显示与隐藏。
v-if
v-show
v-if
值为true显示,值为false隐藏,隐藏:直接 移除DOM结构v-show
值为true显示,值为false隐藏,隐藏:给 DOM 的dispaly
设置为none
- 如果要频繁的切换元素的显示状态,
v-show
性能更好,不用每次都动态添加删除元素 - 如果初始状态为 false ,并且之后显示的状态可能性较小,使用
v-if
更好
1.6.2v-else-if 和 v-else
v-else-if
必须配合 v-if
使用,否则不被识别
<div v-if="type === 'A' ">优秀</div>
<div v-else-if="type === 'B' ">良好</div>
<div v-else-if="type === 'C' ">一般</div>
<div v-else="type === 'D' ">差</div>
1.7 列表渲染条件
vue 提供了
v-for
列表渲染指令,用来辅助开发者基于一个数组来循环渲染一个列表结构。v-for 指令需要使用item in items
形式的特殊语法。
- items 是待循环的数组
- item 是被循环的每一项
v-for 还支持一个可选的第二个参数,即当前项的索引。语法格式:
(item,index) in items
item 和 index 都是形参
<div id="app">
<table class="table table-border table-hover table-striped">
<thead>
<th>索引</th>
<th>ID</th>
<th>姓名</th>
</thead>
<tbody>
<tr v-for="(item,index) in list">
<td>{{ index }} </td>
<td>{{ item.id }} </td>
<td>{{ item.name }} </td>
</tr>
</tbody>
</table>
</div>
- 官方建议:只要用到了
v-for
指令,那么一定要绑定一个:key
属性 - 最好将
id
作为 key 的值 - 对 key 的值得类型,是有要求的,字符串或者数值类型
- key 值不允许重复,否则报错
Duplicate keys detected
- 使用 index 的值当做 key 的值没有任何意义,index 的值不具有唯一性
1.7 品牌列表案例源码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
<title>Document</title>
</head>
<body>
<div id="app">
<div style="width: 30%;position: relative;margin: 20px;">
<form @submit.prevent="add" class="bs-example bs-example-form" role="form" style="width: 80%;">
<div class="input-group">
<span class="input-group-addon">品牌名称</span>
<input type="text" class="form-control" placeholder="请输入品牌名称" v-model.trim="brand">
</div>
<button type="submit" class="btn btn-success" style="position: absolute;right: 0;top: 0;">添加</button>
</form>
</div>
<div style="width: 80%;border-top: 1px solid #cfcfcf;margin-left: 20px;">
<table class="table table-bordered table-hover table-striped">
<thead>
<th>#</th>
<th>品牌名称</th>
<th>状态</th>
<th>创建时间</th>
<th>操作</th>
</thead>
<tbody>
<tr v-for="item in list" :key="item.id">
<td>{{ item.id }} </td>
<td>{{ item.name }} </td>
<td>
<div class="checkbox">
<label>
<!-- v-model 内部会判断属性 text,checkbox,radio 最后确定是 value,checked... -->
<input type="checkbox" v-model="item.status">
<span v-if="item.status === false">已禁用</span>
<span v-else>已启用</span>
</label>
</div>
</td>
<td>{{ item.time}} </td>
<td>
<span @click="remove(item.id)" style="cursor: pointer;">删除</span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<script src="./lib/vue.js"></script>
<script>
// 创建 vue 实例对象
const vm = new Vue({
el: '#app',
data: {
list: [
{ id: 1, name: '宝马',status: true,time: new Date()},
{ id: 2, name: '奔驰',status: false,time: new Date()},
{ id: 3, name: '奥迪',status: true,time: new Date()},
],
brand: '',
// 下一个可用的 id
nextId: 4
},
methods: {
// 点击链接删除
remove(id) {
console.log(id)
this.list = this.list.filter(item => item.id !== id)
},
add(){
console.log(this.brand)
if(this.brand === ''){
return window.alert('必须填写品牌名称!!!')
}
let obj = {
id: this.nextId,
name: this.brand,
status: true,
time: new Date()
}
this.list.push(obj)
this.brand = ''
this.nextId ++
}
}
})
</script>
</body>
</html>