vue 中的指令按照不同的用途可以分为如下 6 大类:
内容渲染指令
属性绑定指令
事件绑定指令
双向绑定指令
条件渲染指令
列表渲染指令
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">
<title>Documenttitle>
<script src="./vue-2.6.12.js">script>
head>
<body>
<div id="app">
<p v-text="username">p>
<p v-text="gender">性别p>
div>
<script>
const vm = new Vue({
el: '#app',
data: {
username: '张三',
gender: '男'
}
})
script>
body>
html>
vue 提供的 {{ }} 语法,专门用来解决 v-text 会覆盖默认文本内容的问题。这种 {{ }} 语法的专业名称是插值表达式(英文名为:Mustache)
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">
<title>Documenttitle>
<script src="./vue-2.6.12.js">script>
head>
<body>
<div id="app">
<p>姓名:{{username}}p>
<p>性别:{{gender}}p>
div>
<script>
const vm = new Vue({
el: '#app',
data: {
username: '张三',
gender: '男'
}
})
script>
body>
html>
如果要把包含 HTML 标签的字符串渲染为页面的 HTML 元素,则需要用到 v-html 这个指令
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">
<title>Documenttitle>
<script src="./vue-2.6.12.js">script>
head>
<body>
<div id="app">
<p>姓名:{{username}}p>
<p>性别:{{gender}}p>
<p>---------------------p>
<p v-text="desc">p>
<p>{{desc}}p>
<p v-html="desc">p>
div>
<script>
const vm = new Vue({
el: '#app',
data: {
username: '张三',
gender: '男',
desc:'abc
'
}
})
script>
body>
html>
初始内容为:
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">
<title>Documenttitle>
<script src="./vue-2.6.12.js">script>
head>
<body>
<div id="app">
<input type="text" placeholder="默认内容">
div>
<script>
const vm = new Vue({
el:'#app',
data:{
inputValue:'请输入内容',
imgSrc:'./images/girl.jpg'
},
})
script>
body>
html>
现在想要将placeholder的属性进行动态绑定,就需要在这个属性的前面加上v-bind
而v-bind可以简写为 :
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">
<title>Documenttitle>
<script src="./vue-2.6.12.js">script>
head>
<body>
<div id="app">
<input type="text" v-bind:placeholder="inputValue">
<br>
<br>
<br>
<img :src="imgSrc" height="500px">
div>
<script>
const vm = new Vue({
el:'#app',
data:{
inputValue:'请输入内容',
imgSrc:'./images/girl.jpg'
},
})
script>
body>
html>
在 vue 提供的模板渲染语法中,除了支持绑定简单的数据值之外,还支持 Javascript 表达式的运算
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">
<title>Documenttitle>
<script src="./vue-2.6.12.js">script>
head>
<body>
<div id="app">
<p>{{number + 1}}p>
<p>{{ok ? '正确':'错误'}}p>
<p>{{message.split('').reverse().join('')}}p>
<p :id="'list - ' + id">xxxp>
<p>{{user.name}}p>
div>
<script>
const vm = new Vue({
el: '#app',
data: {
// 数值
number: 99,
// 布尔值
ok: true,
// 字符串
message: 'ABC',
// id值
id: 3,
// 用户的信息对象
user: {
name: '张三',
age: 34,
}
},
})
script>
body>
html>
vue 提供了 v-on 事件绑定指令,用来辅助程序员为 DOM 元素绑定事件监听。
注意:原生 DOM 对象有 onclick、oninput、onkeyup 等原生事件,替换为 vue 的事件绑定形式后,分别为:v-on:click、v-on:input、v-on:keyup
通过 v-on 绑定的事件处理函数,需要在 methods 节点中进行声明
由于 v-on 指令在开发中使用频率非常高,因此提供了简写形式 @
语法格式为 v-on:事件名称=“时间处理函数的名称”。例如 v-on:click=“addCount”
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">
<title>Documenttitle>
<script src="./vue-2.6.12.js">script>
head>
<body>
<div id="app">
<h3>count 的值为:{{count}}h3>
<button v-on:click="addCount">+1button>
div>
<script>
const vm = new Vue({
el: '#app',
data: {
// 计数器的值
count: 0,
},
methods: {
// 点击按钮,让count值自增1
addCount() {//事件处理函数的名字
// this表示当前new出来的vm实例对象
// 通过this可以访问到data中的数据
this.count += 1
},
},
})
script>
body>
html>
v-on还可以简写
<body>
<div id="app">
<h3>count 的值为:{{count}}h3>
<button v-on:click="addCount">+1button>
<br>
<button @click="addCount">+1button>
<br>
<button @click="count += 1">+1button>
div>
在原生的 DOM 事件绑定中,可以在事件处理函数的形参处,接收事件对象 event。同理,在 v-on 指令(简写为 @ )所绑定的事件处理函数中,同样可以接收到事件对象 event。
以下的例子是接收事件对象的背景颜色,改变按钮的颜色
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">
<title>Documenttitle>
<script src="./vue-2.6.12.js">script>
head>
<body>
<div id="app">
<p>{{count}}p>
<button @click="addCount">+1button>
div>
<script>
const vm = new Vue({
el: '#app',
data: {
count: 0,
},
methods: {
// 点击按钮,让count自增1
addCount(e) {
// 获取当前时间对象的背景颜色
const nowBgColor = e.target.style.backgroundColor
e.target.style.backgroundColor = nowBgColor == 'red' ? '' : 'red'
console.log(nowBgColor)
this.count += 1
},
},
})
script>
body>
html>
在使用 v-on 指令绑定事件时,可以使用 ( ) 进行传参。当需要传值的时候就需要加上小括号,不需要传值的时候可以省略。
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">
<title>Documenttitle>
<script src="./vue-2.6.12.js">script>
head>
<body>
<div id="app">
<p>{{count}}p>
<button @click="addCount">+1button>
<button @click="addCount2(2)">+2button>
div>
<script>
const vm = new Vue({
el: '#app',
data: {
count: 0,
},
methods: {
// 点击按钮,让count自增1
addCount() {
this.count += 1
},
// 点击按钮,让count自增传过来的参数
addCount2(step) {
this.count += step
},
},
})
script>
body>
html>
如果想要在自增+2的同时还要改变按钮的背景颜色,这个时候需要既获取传的参数又要获取事件对象e。但是事件对象会被参数覆盖。
$event 是 vue 提供的特殊变量,用来表示原生的事件参数对象 event。可以解决事件参数对象 event 被覆盖的问题。
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">
<title>Documenttitle>
<script src="./vue-2.6.12.js">script>
head>
<body>
<div id="app">
<p>{{count}}p>
<button @click="addCount">+1button>
<button @click="addCount2(2,$event)">+2button>
div>
<script>
const vm = new Vue({
el: '#app',
data: {
count: 0,
},
methods: {
// 点击按钮,让count自增1
addCount() {
this.count += 1
},
// 点击按钮,让count自增传过来的参数
addCount2(step,e) {
const bgColor = e.target.style.backgroundColor
e.target.style.backgroundColor = bgColor === 'red' ? '' : 'red'
this.count += step
},
},
})
script>
body>
html>
在事件处理函数中调用 preventDefault() 或 stopPropagation() 是非常常见的需求。因此,vue 提供了事件修饰符的概念,来辅助程序员更方便的对事件的触发进行控制。
事件修饰符 | 说明 |
---|---|
.prevent | 阻止默认行为(例如:阻止 a 连接的跳转、阻止表单的提交等) |
.stop | 阻止事件冒泡 |
.capture | 以捕获模式触发当前的事件处理函数 |
.once | 绑定的事件只触发1次 |
.self | 只有在 event.target 是当前元素自身时触发事件处理函数 |
最初的代码以及实现的效果
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<style>
.inner {
line-height: 100px;
background-color: aliceblue;
font-size: 13px;
text-align: center;
}
.outer {
background-color: bisque;
padding: 50px;
font-size: 13px;
}
.box {
background-color: coral;
padding: 50px;
}
style>
head>
<body>
<div id="app">
<h4>① .prevent 事件修饰符的应用场景h4>
<a href="https://www.baidu.com" @click="onLinkClick">百度首页a>
<hr />
<h4>② .stop 事件修饰符的应用场景h4>
<div class="outer" @click="onOuterClick">
外层的 div
<div class="inner" @click="onInnerClick">内部的 divdiv>
div>
<hr />
<h4>③ .capture 事件修饰符的应用场景h4>
<div class="outer" @click="onOuterClick">
外层的 div
<div class="inner" @click="onInnerClick">内部的 divdiv>
div>
<hr />
<h4>④ .once 事件修饰符的应用场景h4>
<div class="inner" @click="onInnerClick">内部的 divdiv>
<hr />
<h4>⑤ .self 事件修饰符的应用场景h4>
<div class="box" @click="onBoxClick">
最外层的 box
<div class="outer" @click="onOuterClick">
中间的 div
<div class="inner" @click="onInnerClick">内部的 divdiv>
div>
div>
<hr />
div>
<script src="./lib/vue-2.6.12.js">script>
<script>
const vm = new Vue({
el: '#app',
// 声明处理函数的节点
methods: {
// 超链接的点击事件处理函数
onLinkClick() {
alert('ok')
},
// 点击了外层的 div
onOuterClick() {
console.log('触发了 outer 的 click 事件处理函数')
},
// 点击了内部的 div
onInnerClick() {
console.log('触发了 inner 的 click 事件处理函数')
},
onBoxClick() {
console.log('触发了 box 的 click 事件处理函数')
}
},
})
script>
body>
html>
初始页面是点击百度首页字符后跳转到百度的首页。
如果不想点击后就跳转到百度就需要使用 .prevent 事件修饰符
执行后的效果就是点击 百度首页 只会出现一个弹窗 ok
<h4>① .prevent 事件修饰符的应用场景h4>
<a href="https://www.baidu.com" @click.prevent="onLinkClick">百度首页a>
事件冒泡就是指父元素和子元素有相同的事件,当触发子元素事件时,会向上冒泡,同时也会触发父元素事件.
源程序的效果是点击内部的盒子会在控制台显示“触发了 inner 的 click 事件处理函数”,随后出发外部盒子的函数,显示“触发了 outer 的 click 事件处理函数”。
如果不想出发外部盒子的函数(也就是不冒泡),可以使用.stop
<h4>② .stop 事件修饰符的应用场景h4>
<div class="outer" @click="onOuterClick">
外层的 div
<div class="inner" @click.stop="onInnerClick">内部的 divdiv>
div>
初始效果
使用.stop后
默认的触发方式是冒泡,想要改为捕获的方式触发就要使用.capture
使用后的效果就是点击内部,先触发的外部,然后触发的内部。
<h4>③ .capture 事件修饰符的应用场景h4>
<div class="outer" @click="onOuterClick">
外层的 div
<div class="inner" @click.capture="onInnerClick">内部的 divdiv>
div>
事件触发的次数默认是不限制的,想要事件只触发一次,就可以使用.once
<h4>④ .once 事件修饰符的应用场景h4>
<div class="inner" @click.once="onInnerClick">内部的 divdiv>
使用.once后,点击7次,依旧只触发了1次
事件触发默认都是冒泡触发的,但是如果想让中间的事件只有在点击的时候才触发就需要使用.self
<h4>⑤ .self 事件修饰符的应用场景h4>
<div class="box" @click="onBoxClick">
最外层的 box
<div class="outer" @click.self="onOuterClick">
中间的 div
<div class="inner" @click="onInnerClick">内部的 divdiv>
div>
div>
初始
使用后
在监听键盘事件时,我们经常需要判断详细的按键。此时,可以为键盘相关的事件添加按键修饰符。
以下例子为 监测键盘,按下回车在控制台打印出文本框内写入的值,按下esc清空文本框。
当然将‘enter’和‘esc’改为其他按键也可以,比如‘a’
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">
<title>Documenttitle>
<script src="./vue-2.6.12.js">script>
head>
<body>
<div id="app">
<input type="text" @keyup.enter="submit" @keyup.esc="clearInput">
div>
<script>
const vm = new Vue({
el: '#app',
data: {
},
methods: {
submit(e) {
// 获取文本框最新的值
console.log('按下了 enter 键,最新的值为:' + e.target.value)
},
// 清空文本框的值
clearInput(e) {
e.target.value = ''
},
},
})
script>
body>
html>
vue 提供了 v-model 双向数据绑定指令,用来辅助开发者在不操作 DOM 的前提下,快速获取表单的数据。
注意:v-model 指令只能配合表单元素一起使用!
初始效果
想要在文本框内也将名字渲染进去,再将省份的value值也同步上去,就需要使用双向绑定
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">
<title>Documenttitle>
<script src="./vue-2.6.12.js">script>
head>
<body>
<div id="app">
<p>用户名是:{{username}}p>
<input type="text" v-model="username">
<hr>
<p>选中的省份是:{{province}}p>
<select v-model="province">
<option value="">请选择option>
<option value="1">北京option>
<option value="2">上海option>
<option value="3">河北option>
select>
div>
<script>
const vm = new Vue({
el: '#app',
data: {
// 姓名
username: '张三',
// 省份
province: ''
},
methods: {
},
})
script>
body>
html>
为了方便对用户输入的内容进行处理,vue 为 v-model 指令提供了 3 个修饰符
修饰符 | 作用 | 示例 |
---|---|---|
.number | 自动将用户的输入值转为数值类型 |
条件渲染指令用来辅助开发者按需控制 DOM 的显示与隐藏。
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">
<title>Documenttitle>
<script src="./vue-2.6.12.js">script>
head>
<body>
<div id="app">
<button @click="flag =! flag">Toggle Flagbutton>
<p v-if="flag">请求成功 --- 被 v-if 控制p>
<p v-show="flag">请求成功 --- 被 v-show 控制p>
div>
<script>
const vm = new Vue({
el: '#app',
data: {
// flag用来控制元素的显示与隐藏
// 值为true时显示元素
// 值为false时隐藏元素
flag: true,
},
methods: {
},
})
script>
body>
html>
实现原理不同:
⚫ v-if 指令会动态地创建或移除 DOM 元素,从而控制元素在页面上的显示与隐藏;
⚫ v-show 指令会动态为元素添加或移除 style=“display: none;” 样式,从而控制元素的显示与隐藏;
性能消耗不同:
v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。
⚫ 如果需要非常频繁地切换,则使用 v-show 较好
⚫ 如果在运行时条件很少改变,则使用 v-if 较好
v-if 可以单独使用,或配合 v-else 指令一起使用
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">
<title>Documenttitle>
<script src="./vue-2.6.12.js">script>
head>
<body>
<div id="app">
<p v-if="type === 'A'">优秀p>
<p v-else-if="type === 'B'">良好p>
<p v-else-if="type === 'C'">合格p>
<p v-else>差p>
div>
<script>
const vm = new Vue({
el: '#app',
data: {
type: 'B'
},
methods: {
},
})
script>
body>
html>
vue 提供了 v-for 指令,用来辅助开发者基于一个数组来循环渲染相似的 UI 结构。
v-for 指令需要使用 item in items 的特殊语法,其中:
⚫ items 是待循环的数组
⚫ item 是当前的循环项
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">
<title>Documenttitle>
<script src="./vue-2.6.12.js">script>
head>
<body>
<div id="app">
<ul>
<li v-for="user in list">姓名是:{{user.name}}li>
ul>
div>
<script>
const vm = new Vue({
el: '#app',
data: {
// 用户列表的数据
list: [
{ id: 1, name: '张三' },
{ id: 2, name: '李四' },
],
},
methods: {
},
})
script>
body>
html>
v-for 指令还支持一个可选的第二个参数,即当前项的索引。语法格式为 (item, index) in items。
注意:v-for 指令中的 item 项和 index 索引都是形参,可以根据需要进行重命名。例如 (user, i) in userlist
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">
<title>Documenttitle>
<script src="./vue-2.6.12.js">script>
head>
<body>
<div id="app">
<ul>
<li v-for="(user,i) in list">索引是:{{i}},姓名是:{{user.name}}li>
ul>
div>
<script>
const vm = new Vue({
el: '#app',
data: {
// 用户列表的数据
list: [
{ id: 1, name: '张三' },
{ id: 2, name: '李四' },
],
},
methods: {
},
})
script>
body>
html>
当列表的数据变化时,默认情况下,vue 会尽可能的复用已存在的 DOM 元素,从而提升渲染的性能。但这种默认的性能优化策略,会导致有状态的列表无法被正确更新。
为了给 vue 一个提示,以便它能跟踪每个节点的身份,从而在保证有状态的列表被正确更新的前提下,提升渲染的性能。此时,需要为每项提供一个唯一的 key 属性
比如:
现在选中了李四这个选项,然后添加王五
点击添加后:
列表的顺序和选中的状态混乱
解决方案
因为数组中每个user都有唯一的id作为区分,所以添加属性绑定,将id绑定进去方便区分每个user。
:key=“user.id”
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
head>
<body>
<div id="app">
<div>
<input type="text" v-model="name">
<button @click="addNewUser">添加button>
div>
<ul>
<li v-for="(user, index) in userlist" :key="user.id">
<input type="checkbox" />
姓名:{{user.name}}
li>
ul>
div>
<script src="./vue-2.6.12.js">script>
<script>
const vm = new Vue({
el: '#app',
data: {
// 用户列表
userlist: [
{ id: 1, name: '张三' },
{ id: 2, name: '李四' }
],
// 输入的用户名
name: '',
// 下一个可用的 id 值
nextId: 3
},
methods: {
// 点击了添加按钮
addNewUser() {
this.userlist.unshift({ id: this.nextId, name: this.name })
this.name = ''
this.nextId++
}
},
})
script>
body>
html>
① key 的值只能是字符串或数字类型
② key 的值必须具有唯一性(即:key 的值不能重复)
③ 建议把数据项 id 属性的值作为 key 的值(因为 id 属性的值具有唯一性)
④ 使用 index 的值当作 key 的值没有任何意义(因为 index 的值不具有唯一性)
⑤ 建议使用 v-for 指令时一定要指定 key 的值(既提升性能、又防止列表状态紊乱)