Vue——02 Vue指令和Vue对象的配置项
2 Vue指令和Vue对象的配置项
- Vue 会根据不同的指令,针对标签实现不同的功能;
- 指令:带有
v-
前缀 的特殊标签属性。
2.1 v-html
-
作用:设置元素里的innerHTML;
-
语法:
v-html = "表达式"
; -
例:
<div v-html="str"></div>
2.2 v-show
-
作用:控制元素显示隐藏;
-
语法:
v-show = "表达式"
,表达式值为true
时显示元素,为false
时隐藏元素; -
原理:通过是否给元素添加
display: none
来控制显示隐藏; -
使用场景:需要频繁切换元素的显示隐藏的场景。例如下面的购物车元素,当鼠标放到该元素上时,显示购物车列表:
2.3 v-if
-
作用:基于条件判断来控制元素显示隐藏;
-
语法:
v-if = "表达式"
,表达式值为true
时显示元素,为false
时隐藏元素; -
原理:基于条件判断,来决定是否创建或移除元素;
-
使用场景:对于要么显示,要么隐藏的元素。比如:
2.4 v-else和v-else-if
-
作用:辅助
v-if
进行判断渲染; -
语法:
v-else
、v-else-if = "表达式"
; -
注意: 需要紧挨着
v-if
一起使用; -
例:
<div id="app"><p v-if="gender === 1">性别:男</p><p v-else>性别:女</p><hr><p v-if="score >= 90">成绩评定A</p><p v-else-if="score >= 70">成绩评定B</p><p v-else-if="score >= 60">成绩评定C</p><p v-else>成绩评定D</p> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script> <script>const app = new Vue({el: '#app',data: {gender: 2,score: 95 //通过改变score的值,来显示隐藏对应的元素}}) </script>
2.5 v-on
-
作用:注册事件,即添加数据监听后,提供数据处理逻辑;
-
语法1:
v-on:事件名 = "内联语句"
或简写@事件名 = "内联语句"
;<button v-on:click = "count--">-</button> <span>{{ count }}</span> <button v-on:click = "count++">+</button>//简写 <button @click = "count--">-</button> <span>{{ count }}</span> <button @click = "count++">+</button>
-
语法2:
v-on:事件名 = "methods中的函数名"
或简写@事件名 = "methods中的函数名"
;methods
函数内的this
指向 Vue 实例;
<div id="app"><button @click = "fn">切换显示隐藏</button><h1 v-show="isShow">嘿嘿</h1> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script> <script>const app = new Vue({el: '#app',data: {isShow: true},methods: {fn () {//app.isShow = !app.isShow//或者this.isShow = !this.isShow}}}) </script>
-
基于语法2的调用传参:
v-on:事件名 = "methods中的函数名(参数1, 参数2)"
或简写@事件名 = "methods中的函数名(参数1, 参数2)"
;<div id="app"><div class="box"><h3>自动售货机</h3><button @click = "buy(5)">可口可乐5元</button><button @click = "buy(7)">百事可乐7元</button></div><p>账户余额:{{ money }}元</p> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script> <script>const app = new Vue({el: '#app',data: {money: 100},methods: {buy (price) {this.money -= price}}}) </script>
2.6 v-bind
2.6.1 操作基本属性
-
作用:动态地设置html元素的标签属性,如
src
、url
、title
… -
语法:
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>图片切换案例</title> </head><body><div id="app"><button v-show="index > 0" @click="index--">上一页</button><div><img v-bind:src="list[index]" alt=""></div><button v-show="index < list.length -1 " @click="index++">下一页</button></div><script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script><script>const app = new Vue({el: '#app',data: {index: 0,list: ['./imgs/11-00.gif','./imgs/11-01.gif','./imgs/11-02.gif','./imgs/11-03.gif','./imgs/11-04.png','./imgs/11-05.png',]}})</script> </body></html>
2.6.2 操作class属性
-
语法1:
.class="对象"
;-
键是类名,值是布尔值。若值为
true
,则有这个类;若值为false
,则无这个类;<div class="box" :class="{ 类名1: 布尔值, 类名2: 布尔值 }"></div>
-
使用场景:来回切换一个类名时可以使用;
-
-
语法2:
.class="数组"
;-
数组中所有的类,都会添加到该元素上,本质就是一个
class
列表;<div class="box" :class="[ 类名1, 类名2, 类名3 ]"></div>
-
批量添加或删除类时可以使用。
-
tab导航高亮
<!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>tab导航高亮</title><style>* {margin: 0;padding: 0;}ul {display: flex;border-bottom: 2px solid #e01222;padding: 0 10px;}li {width: 100px;height: 50px;line-height: 50px;list-style: none;text-align: center;}li a {display: block;text-decoration: none;font-weight: bold;color: #333333;}li a.active {background-color: #e01222;color: #fff;}</style>
</head><body><div id="app"><ul><li v-for="(item, index) in list" :key="item.id" @click="activeIndex = index"><a :class="{ active: index === activeIndex }" href="#">{{ item.name }}</a></li></ul></div><script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><script>const app = new Vue({el: '#app',data: {activeIndex: 0, //记录高亮的元素的下标list: [{ id: 1, name: '京东秒杀' },{ id: 2, name: '每日特价' },{ id: 3, name: '品类秒杀' }]}})</script>
</body></html>
2.6.3 操作style
-
语法:
:style = "样式对象"
;<div class="box" :style="{ CSS属性1: CSS属性值, CSS属性2: CSS属性值 }"></div>
-
需要动态地设置某个具体属性时使用。
进度条效果
<!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>Document</title><style>.progress {height: 25px;width: 400px;border-radius: 15px;background-color: #272425;border: 3px solid #272425;box-sizing: border-box;margin-bottom: 30px;}.inner {width: 50%;height: 20px;border-radius: 10px;text-align: right;position: relative;background-color: #409eff;background-size: 20px 20px;box-sizing: border-box;transition: all 1s;}.inner span {position: absolute;right: -20px;bottom: -25px;}</style>
</head><body><div id="app"><div class="progress"><!-- 注意下面的 % 需要加单引号 --><div class="inner" :style="{width: percent + '%' }"><span>{{ percent }}%</span></div></div><button @click="percent = 25">设置25%</button><button @click="percent = 50">设置50%</button><button @click="percent = 75">设置75%</button><button @click="percent = 100">设置100%</button></div><script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><script>const app = new Vue({el: '#app',data: {percent: 0}})</script>
</body></html>
2.7 v-for
-
作用:基于数据循环, 多次渲染某个元素;
-
语法:
v-for = "(item, index) in 数组名
;item
对应每一项的元素,index
对应下标;- 也可以省略
index
,直接写:v-for = "item in 数组名"
;
-
例:
<div id="app"><h3>书架</h3><ul><li v-for="(item, index) in booksList"><span>{{ item.name }}</span><span>{{ item.author }}</span><!-- 注册点击事件,通过id来删除数组中的对应项 --><button @click="del(item.id)">删除</button></li></ul> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script> <script>const app = new Vue({el: '#app',data: {booksList: [{ id: 1, name: '《红楼梦》', author: '曹雪芹' },{ id: 1, name: '《西游记》', author: '吴承恩' },{ id: 1, name: '《水浒传》', author: '施耐庵' },{ id: 1, name: '《三国演义》', author: '罗贯中' }]},methods: {del (id) {//调用filter()函数,该函数会保留满足条件的对应项得到一个新数组,将该新数组赋给原数组即可this.booksList = this.booksList.filter(item => item.id !== id)}}}) </script>
-
要给
v-for
所在元素加一个==key
属性==作为该列表项的唯一标识,便于Vue对列表项进行正确的排序复用,接上例:<li v-for="(item, index) in booksList" :key="item.id">
- 若不加
key
属性,则v-for
是对元素进行原地复用,即不删除原本的元素,只是将未被删除的数据重新渲染上去; - 若加了
key
属性,则v-for
会将对应的元素删除,再将剩余的元素重新在页面上排列; - 注意:
key
属性的值只能是字符串或数字类型;key
属性的值必须具有唯一性;- 推荐使用每一条数据对应的
id
作为key
属性的值,不推荐使用index
,因为index
会变化、不对应。
- 若不加
2.8 v-model
-
作用:表单元素使用,可以实现双向数据绑定,即可以快速获取或设置表单元素内容;
- 双向数据绑定,也称数据双向渲染,即当数据变量则视图自动更新,当视图变化则数据自动更新;
-
语法:
v-model='变量'
; -
例:
<div id="app">账户:<input type="text" v-model="username"> <br><br>密码:<input type="password" v-model="password"> <br><br><button @click="login">登录</button><button @click="reset">重置</button> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script> <script>const app = new Vue({el: '#app',data: {username: '',password: ''},methods: {login () {//可以获取到用户名和密码console.log(this.username, this.password)},reset () {this.username = ''this.password = ''}}}) </script>
-
v-model
会根据控件类型自动选取正确的方法来更新元素。如:- 输入框
input:text
,value; - 文本域
textarea
,value; - 复选框
input:checkbox
,checked; - 单选框
input:radio
,checked; - 下拉菜单
select
,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>表单信息收集</title><style>textarea {display: block;width: 240px;height: 100px;margin: 10px 0;}</style> </head><body><div id="app"><h3>小黑学习网</h3>姓名:<input type="text" v-model="username"><br><br>是否单身:<input type="checkbox" v-model="isSingle"><br><br><!-- 前置理解:1. name: 给单选框加上 name 属性 可以分组 → 同一组互相会互斥2. value: 给单选框加上 value 属性,用于提交给后台的数据结合 Vue 使用 → v-model-->性别:<input type="radio" name="gender" value="1" v-model="gender">男<input type="radio" name="gender" value="2" v-model="gender">女<br><br><!-- 前置理解:1. option 需要设置 value 值,提交给后台2. select 的 value 值,关联了选中的 option 的 value 值结合 Vue 使用 → v-model-->所在城市:<select v-model="cityId"><option value="101">北京</option><option value="102">上海</option><option value="103">成都</option><option value="104">南京</option></select><br><br>自我描述:<textarea v-model="desc"></textarea><button>立即注册</button></div><script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><script>const app = new Vue({el: '#app',data: {username: '',isSingle: true,gender: "2",cityId: '101',desc: ""}})</script> </body></html>
2.9 指令修饰符
- 通过
.
指明一些指令 后缀,不同后缀封装了不同的处理操作。
2.9.1 事件修饰符
-
@事件名.stop
:调用event.stopPropagation()
,阻止事件继续传播,或者说阻止事件冒泡;<!-- 阻止单击事件继续传播 --> <a @click.stop="doThis"></a>
-
@事件名.prevent
:调用event.preventDefault()
,阻止事件的默认行为;<!-- 提交事件不再重载页面 --> <form @submit.prevent="onSubmit"></form>
-
@事件名.capture
:添加事件监听器时使用事件捕获模式,即在子组件中捕获父组件事件;<!-- 添加事件监听器时使用事件捕获模式 --> <div @click.capture="doThis">...</div>
-
@事件名.self
:确保事件只在监听器绑定的元素上触发时,而不会冒泡到其子元素或祖先元素上; -
@事件名.once
:只触发一次。不像其它只能对原生的 DOM 事件起作用的修饰符,.once
修饰符还能被用到自定义的组件事件上; -
@事件名.passive
:告诉浏览器你不想阻止事件的默认行为,该修饰符尤其能够提升移动端的性能;-
<!-- 滚动事件的默认行为 (即滚动行为) 将会立即触发,而不会等待 onScroll 完成,即不会调用 preventDefault() --> <div @scroll.passive="onScroll">...</div>
-
不要把
.passive
和.prevent
一起使用,因为.prevent
将会被忽略,同时浏览器可能会向你展示一个警告,.passive
会告诉浏览器你不想阻止事件的默认行为。
-
-
注意:使用修饰符时,顺序很重要,相应的代码会以同样的顺序产生。
- 例:用
@click.prevent.self
会阻止所有的点击,而@click.self.prevent
只会阻止对元素自身的点击。
- 例:用
2.9.2 按键修饰符
-
按键修饰符有,即在
@keyup
后可以加:.enter
.tab
.delete
(捕获“删除”和“退格”键).esc
.space
.up
.down
.left
.right
-
例:
<!-- 只有在 key 是 Enter 时,即用户按下回车键后,调用 submit 方法 --> <input @keyup.enter="submit">
2.9.3 系统修饰符
-
可以用以下修饰符来实现仅在按下相应按键时才触发事件的监听器:
-
.ctrl
-
.alt
-
.shift
-
.meta
(Mac的Command键,Windows的Win键) -
例:
<!-- Alt + C --> <input v-on:keyup.alt.67="clear"><!-- Ctrl + Click --> <div v-on:click.ctrl="doSomething">Do something</div>
-
-
.exact
修饰符允许控制由精确的系统修饰符组合触发的事件:<!-- 以下这种情况,即使 Alt 或 Shift 被一同按下时也会触发 --> <button v-on:click.ctrl="onClick">A</button><!-- 以下这种情况,有且只有 Ctrl 被按下的时候才触发 --> <button v-on:click.ctrl.exact="onCtrlClick">A</button><!-- 没有任何系统修饰符被按下,仅点击该按钮的时候才触发 --> <button v-on:click.exact="onClick">A</button>
-
鼠标按钮修饰符,这些修饰符会限制处理函数仅响应特定的鼠标按钮:
.left
.right
.middle
2.9.4 v-model修饰符
v-model.lazy
:将输入事件由默认的input
事件改为change
事件。这意味着数据绑定将在change
事件触发时更新,而不是在每次输入事件触发时更新;v-model.number
:转为数值类型;v-model.trim
:去除首尾空格。
2.10 计算属性
2.10.1 概念及语法
-
概念:基于现有的数据,计算出来的新属性。依赖的数据变化,自动重新计算;
-
语法:
-
声明在Vue对象的
computed
配置项中,用一个计算函数来返回计算的结果,这个计算的结果就是计算属性名;computed: {计算属性名 () {基于现有数据,编写求值逻辑return 结果} },
-
使用方法和普通属性一样,即
{{ 计算属性名}}
;
-
-
例:
<!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>计算属性</title><style>table {border: 1px solid #000;text-align: center;width: 240px;}th,td {border: 1px solid #000;}h3 {position: relative;}</style> </head><body><div id="app"><h3>小黑的礼物清单</h3><table><tr><th>名字</th><th>数量</th></tr><tr v-for="(item, index) in list" :key="item.id"><td>{{ item.name }}</td><td>{{ item.num }}个</td></tr></table><!-- 目标:统计求和,求得礼物总数。注意下面的totalCount不要加(),因为计算属性本质上还是属性 --><p>礼物总数:{{totalCount}} 个</p></div><script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><script>const app = new Vue({el: '#app',data: {// 现有的数据list: [{ id: 1, name: '篮球', num: 1 },{ id: 2, name: '玩具', num: 2 },{ id: 3, name: '铅笔', num: 5 },]},computed: {totalCount() {//利用reduce方法对数组进行求和计算,0是初始值,先赋值给sum,然后将数组元素对sum进行累加let total = this.list.reduce((sum, item) => sum + item.num, 0)return total}}})</script> </body></html>
2.10.2 computed VS methods
computed
计算属性:- 作用:封装了一段对于数据的处理,求得一个结果;
- 语法:
- 写在
computed
配置项中; - 作为属性,直接使用;
- 写在
methods
方法:- 作用:给实例提供一个方法,调用以处理业务逻辑;
- 语法:
- 写在
methods
配置项中; - 作为方法,需要调用。
- 写在
computed
比methods
的好处在于:computed
有缓存特性,可以提升性能;- 缓存特性:计算属性会将计算出来的结果缓存,再次使用直接读取缓存即可。若依赖项变化了,会自动重新计算,并再次缓存。
2.10.3 完整写法
-
计算属性默认的简写,只能读取计算属性的值,不能"修改"。 如果要"修改",需要写计算属性的完整写法。如下:
computed: {计算属性名 () {get(){一段计算的代码逻辑return 结果},set(修改的值) {一段修改的代码逻辑}} },
-
例:
<!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>计算属性完整写法</title> </head><body><div id="app">姓:<input type="text" v-model="firstName"><br>名:<input type="text" v-model="lastName"><br><p>姓名:</p><button @click="changeName">修改姓名</button></div><script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><script>const app = new Vue({el: '#app',data: {firstName: '刘',lastName: '备'},methods: {changeName() {this.fullName = '吕布'}},computed: {fullName: {get() {return this.firstName + this.lastName},set(value) {//在数组上调用 slice() 方法会返回一个新的数组,包含从开始索引到结束索引(但不包括结束索引处的元素)的部分。//在字符串上调用 slice() 方法同样会返回一个新的字符串,包含从开始索引到结束索引(但不包括结束索引处的字符)的部分。this.firstName = value.slice(0, 1)this.lastName = value.slice(1)}}}})</script> </body></html>
- 当点击按钮时,会执行
changeName
方法,该方法会更新fullName
的值,从而触发计算属性的set
方法,进而更新firstName
和lastName
。
- 当点击按钮时,会执行
2.11 watch侦听器(监听器)
-
作用:监视数据变化,执行一些业务逻辑或异步操作;
-
简单语法:直接监视简单类型数据
data: {words: '苹果',obj: {words: '苹果'} }, watch: {//以下的方法会在监听的数据发生变化时被触发执行//newValue表示新值,oldValue表示旧值数据属性名(newValue, oldValue) {一些业务逻辑或异步操作},'对象.属性名'(newValue, oldValue) {一些业务逻辑或异步操作} }
-
完整写法:添加额外配置项
-
deep: true
:对复杂类型深度监视; -
immediate: true
:一进页面就立刻执行一次handler
方法。该属性不是一定要有,依需求而定;data: {obj: {words: '苹果',lang: 'italy'} }, watch: {//以下的方法会在监听的数据发生变化时被触发执行obj: { //注意此处不写 '对象.属性名',而是直接写对象deep: true, //深度监视immediate: true, //一进页面就立刻执行一次handler方法handler (newValue) {一些业务逻辑或异步操作}} }
-