1.理解Vue事件的綁定方式
1.1 原生行內(nèi)事件綁定
說(shuō)明:
-
vue
采用行內(nèi)事件綁定的方式. - 因此在學(xué)習(xí)
vue
事件綁定方式之前,先回顧一下JS的行內(nèi)事件綁定 - 學(xué)習(xí)中對(duì)比
vue
的行內(nèi)事件綁定和JS
原生行內(nèi)事件綁定的不同
示例代碼如下:
<style>
.box{
color:red;
}
.wrap{
color:skyblue;
}
</style>
<div id="app">
<h2 id="box" class="box">Hello World</h2>
<button onclick="changeColor()">點(diǎn)擊切換顏色</button>
</div>
<script>
let className = "box"
function changeColor(){
if(className =='box'){
box.className = className = "wrap"
}else{
box.className = className = "box"
}
}
</script>
注意:
這種原生綁定事件方式不常用,因?yàn)轳詈闲蕴?/p>
onclick屬性值是函數(shù)執(zhí)行字符串,在點(diǎn)擊觸發(fā)后會(huì)把這個(gè)字符串強(qiáng)制轉(zhuǎn)為
js
語(yǔ)句執(zhí)行
vue
采用這種方式綁定事件,
原因在于這種綁定方式比較直觀的處理事件的綁定, 省去了大量獲取DOM的操作.
不用擔(dān)心Vue的問(wèn)題, Vue在采用行內(nèi)事件綁定,內(nèi)部肯定做了大量的優(yōu)化處理
2.v-on(@) 事件的綁定與基本使用
為了讓用戶和你的應(yīng)用進(jìn)行交互,我們可以用 v-on
指令添加一個(gè)事件監(jiān)聽器就斤,通過(guò)事件監(jiān)聽器觸發(fā)事件執(zhí)行程序
2.1 v-on
指令的認(rèn)識(shí)和使用
v-on
指令說(shuō)明
-
v-on
指令和其他指令一樣,通過(guò)v-on
綁定事件后,事件屬性值將不再是字符串,而是表達(dá)式 - 因此接班是表達(dá)式就可以在引號(hào)中做一些基本的操作
<div id="app">
<h2 class="box">點(diǎn)擊次數(shù): {{ count }}</h2>
<!-- 既然click 的值是表達(dá)式,那么我們就可以動(dòng)態(tài)的拿到vue ,data屬性中的數(shù)據(jù),然后操作-->
<button v-on:click="count++">暴擊</button>
</div>
<script>
const vm = new Vue({
el: "#app",
data: {
count: 0
}
})
</script>
示例說(shuō)明:
- 通過(guò)
v-on
指令綁定click
單機(jī)事件 -
v-on
指定綁定事件的屬性值是表達(dá)式,表達(dá)式中可以直接獲取vue
中的數(shù)據(jù) - 因此可以是表達(dá)式中直接對(duì)數(shù)據(jù)進(jìn)行修改
通過(guò)上面的說(shuō)明就能理解,每次點(diǎn)擊都會(huì)修改數(shù)據(jù),數(shù)據(jù)的修改觸發(fā)vue
響應(yīng)系統(tǒng),進(jìn)而改變頁(yè)面顯示
之中直接修改數(shù)據(jù)一般情況下用的比較少,原因在于:
- 通過(guò)
v-on
綁定的事件屬性值雖然是表達(dá)式,但是只能處理單個(gè)表達(dá)式邏輯 - 如果處理復(fù)雜的程序就會(huì)有局限性
- 同時(shí)沒(méi)發(fā)在引號(hào)中使用事件對(duì)象,來(lái)處理事件的細(xì)節(jié)
因此,通常會(huì)選擇在表達(dá)式中綁定vue
的方法,將方法作為事件函數(shù)處理
2.2 v-on
指定綁定methods
方法
調(diào)用在 Vue 實(shí)例中定義的方法
說(shuō)明:
- 在選項(xiàng)對(duì)象屬性
methods
中定義vue
示例的方法 - 通過(guò)方法名將
vue
辦法綁定給事件,作為事件處理函數(shù)使用
示例1:修改上一個(gè)示例,限制點(diǎn)擊次數(shù)
<!-- 限定點(diǎn)擊次數(shù) -->
<div id="app">
<h2 class="box">點(diǎn)擊次數(shù): {{ count }}</h2>
<button v-on:click="handleClick">點(diǎn)擊</button>
</div>
<script>
const vm = new Vue({
el: "#app",
data: {
count: 0
},
methods: {
handleClick(){
let count = this.count;
// 限定顯示最大點(diǎn)擊次數(shù)
this.count = Math.min(++count,5)
}
}
})
</script>
示例2: 翻轉(zhuǎn)消息
<!-- HTML --->
<div id="app-5">
<p>{{ message }}</p>
<button v-on:click="reverseMessage">逆轉(zhuǎn)消息</button>
</div>
<!-- JS --->
<script>
new Vue({
el: "#app-5",
data: {
message: 'Hello Vue.js'
},
methods: {
reverseMessage: function(){
this.message = this.message.split('').reverse().join('')
}
}
})
</script>
示例說(shuō)明:
- 通過(guò)示例,當(dāng)按鈕綁定button被點(diǎn)擊時(shí),就會(huì)觸發(fā)
methods
屬性中的的方法, - 在方法中修改數(shù)據(jù), 當(dāng)數(shù)據(jù)被修改時(shí)觸發(fā)響應(yīng)系統(tǒng), 響應(yīng)系統(tǒng)觸發(fā)視圖的重新渲染,
注意.
methods中方法,不能和data的數(shù)據(jù)重名,因?yàn)閐ata中的數(shù)據(jù)和methods中的方法都會(huì)在Vue初始化時(shí)成為Vue示例的屬性或方法
2.3 事件綁定的簡(jiǎn)寫方式
<!-- 完整語(yǔ)法 -->
<button v-on:click="reverseMessage">逆轉(zhuǎn)消息</button>
<!-- 縮寫 -->
<button @click="reverseMessage">逆轉(zhuǎn)消息</button>
3. 關(guān)于函數(shù)內(nèi)的this指向問(wèn)題
3.1 普通函數(shù)this
方法內(nèi)this默認(rèn)指向?qū)嵗龑?duì)象,就可以通過(guò)實(shí)例對(duì)象處理很多操作
<div id="app">
<!-- 綁定事件觸發(fā)Vue方法 -->
<button @click="reversed">按鈕</button>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
msg: "Hello Vue"
},
methods: {
reversed() {
console.log(this) // 實(shí)例對(duì)象
}
}
})
</script>
點(diǎn)擊結(jié)果
3.2 箭頭函數(shù)中this
如果改為箭頭函數(shù)為如下寫法:
{
reversed:() => {
console.log(this) // 實(shí)例對(duì)象
}
}
那么我們就將實(shí)例中的方法換成箭頭函數(shù)
<div id="app">
<!-- 綁定事件觸發(fā)Vue方法 -->
<button @click="reversed">按鈕</button>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
msg: "Hello Vue"
},
methods: {
reversed:()=> {
console.log(this) // 實(shí)例對(duì)象
}
}
})
</script>
點(diǎn)擊結(jié)果:
4. methods方法中不推薦使用箭頭函數(shù)
其實(shí)在上一小節(jié)中了解方法的不同寫法會(huì)導(dǎo)致this
的不同, 那么就來(lái)羅列一下不推薦使用箭頭函數(shù)的原因
4.1 methods不推薦使用箭頭函數(shù)
不推薦使用功能箭頭函數(shù)說(shuō)明:
1.vue
是以數(shù)據(jù)作為驅(qū)動(dòng)的,數(shù)據(jù)的變化將會(huì)觸發(fā)vue響應(yīng)系統(tǒng),同時(shí)更改頁(yè)面的渲染結(jié)果,
-
vue
以數(shù)據(jù)為驅(qū)動(dòng),也就是說(shuō)我們?cè)谖磥?lái)的操作中將大量操作數(shù)據(jù), - 數(shù)據(jù)被處理為
Vue
實(shí)例vm
上的屬性,那么我們就需要大量的通過(guò)vm
對(duì)象來(lái)調(diào)用數(shù)據(jù) - 甚至
methods
的中的方法也會(huì)掛在在vm
對(duì)象上的, - 因此箭頭函數(shù)會(huì)影響我們對(duì)于數(shù)據(jù)和方法的獲取,因?yàn)榧^函數(shù)
this
是window
也正式因?yàn)檫@些原因,我們不推薦方法使用箭頭函數(shù),因?yàn)檫@樣會(huì)丟失this指向, 那么我們就不能利用this 來(lái)獲取數(shù)據(jù)和其他方法了.
看下面的例子
<div id="app">
<button @click="handleClick">非箭頭函數(shù)中this</button>
<button @click="handleClickTwo">箭頭函數(shù)中的this</button>
</div>
<script>
const vm = new Vue({
el: "#app",
data: {
msg: "hello"
},
methods: {
handleClick(){
console.log(this) // vue實(shí)例化對(duì)象
},
handleClickTwo: () => {
console.log(this) // window 對(duì)象
},
}
})
</script>
這樣我們就會(huì)發(fā)現(xiàn)如果我們使用普通函數(shù), 那么要獲取數(shù)據(jù)就很簡(jiǎn)單
handleClick(){
console.log(this) // vue實(shí)例化對(duì)象
// 利用this 獲取數(shù)據(jù)
console.log(this.msg) // 獲取數(shù)據(jù)
},
總結(jié):
methods屬性中方法函數(shù)中如果不需要操作Vue實(shí)例上的屬性和方法, 可以使用箭頭函數(shù),
但是一般不推薦使用箭頭函數(shù), 原因
- 一是因?yàn)槲覀冸S時(shí)可能需要在方法中獲取Vue實(shí)例的其他數(shù)據(jù)或其他方法,
- 二是統(tǒng)一的編碼風(fēng)格,總不至于有的用箭頭函數(shù),有的不用吧,
4.2 關(guān)于Vue方法里使用箭頭函數(shù)誤區(qū)
但是我們需要避免一個(gè)誤區(qū):
我們推薦不使用箭頭函數(shù)是methods的方法, 不是說(shuō)真?zhèn)€Vue項(xiàng)目里都不能使用箭頭函數(shù),
比如我們?nèi)绻诜椒ɡ镞€有函數(shù),在函數(shù)中需要使用vue實(shí)例化對(duì)象我們這個(gè)時(shí)候用箭頭函數(shù)會(huì)比非箭頭函數(shù)要
例如
<div id="app">
<button @click="handleClick">查看this</button>
</div>
<script>
const vm = new Vue({
el: "#app",
data: {
msg: "hello"
},
methods: {
handleClick(){
console.log(this) // vue實(shí)例化對(duì)象
// 延遲修改數(shù)據(jù)
// 1.方法內(nèi)使用普通函數(shù),查看普通函數(shù)中this
setTimeout(function(){
console.log(this) // window 對(duì)象
// 這個(gè)是有要修改數(shù)據(jù),還的使用vm
vm.msg = "wrod"
}, 1000)
// 2.方法內(nèi)使用箭頭函數(shù), 查看函數(shù)內(nèi)this
setTimeout(() => {
console.log(this) // vue實(shí)例對(duì)象
// 這個(gè)是有修改數(shù)據(jù),依然可以使用this
this.msg = "wuwei"
}, 2000)
},
}
})
</script>
通過(guò)示例就能看出,用不用箭頭函數(shù),完全看自己的需求, 而不是說(shuō)不推薦使用箭頭函數(shù),就整個(gè)Vue項(xiàng)目中一個(gè)箭頭函數(shù)都不用了,
要關(guān)注一下是哪里不推薦使用箭頭函數(shù).
因此:
Vue中是不是用箭頭函數(shù),完全看你自身的情況,千萬(wàn)不要聽人說(shuō)Vue不推薦使用箭頭函數(shù),就整個(gè)Vue項(xiàng)目中一個(gè)箭頭函數(shù)都不用, 用不用,看this
5. 關(guān)于方法的事件對(duì)象
在調(diào)用方法的時(shí)候有兩種情況,一種是不加括號(hào),一種加括號(hào)
<!--不加括號(hào) -->
<button @click="reversed">點(diǎn)擊</button>
<!--加括號(hào) -->
<button @click="reversed()">點(diǎn)擊</button>
<button @click="reversed(12345)">點(diǎn)擊</button>
那么很明顯使用加括號(hào)的方式是為了傳遞參數(shù)給事件函數(shù),
那么我們就來(lái)看看不同的事件綁定方式對(duì)于事件對(duì)象的影響
5.1 不加括號(hào)
不加括號(hào)的情況下,默認(rèn)第一個(gè)形參就是事件對(duì)象
<div id="app">
<!-- 不加括號(hào)綁定事件 -->
<button @click="reversed">點(diǎn)擊</button>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
msg: "Hello Vue"
},
methods: {
reversed:(ev)=> {
console.log(ev) // 事件對(duì)象
}
}
})
</script>
頁(yè)面點(diǎn)擊結(jié)果:
5.2 加括號(hào)
如果加括號(hào)無(wú)論你傳不傳實(shí)參,形參默認(rèn)就是要接受你傳遞的實(shí)參
<div id="app">
<!-- 加括號(hào)未傳參 -->
<button @click="reversed()">點(diǎn)擊</button>
<!-- 加括號(hào)傳參 -->
<button @click="reversed(123)">點(diǎn)擊2</button>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
msg: "Hello Vue"
},
methods: {
reversed:(ev)=> {
console.log(ev) // 事件對(duì)象
}
}
})
</script>
點(diǎn)擊后的結(jié)果
事件綁定加括號(hào)說(shuō)明
通過(guò)示例發(fā)現(xiàn),加括號(hào)沒(méi)有傳參是,事件函數(shù)的第一個(gè)形參是
undefined
因?yàn)闆](méi)有接受到實(shí)參如果加括號(hào)綁定事件, 事件執(zhí)行傳遞了實(shí)參,那么事件函數(shù)的第一個(gè)形參就是傳遞過(guò)來(lái)的實(shí)參
那么問(wèn)題來(lái)了,如果我需要傳參時(shí)如何獲取事件對(duì)象呢
5.3 綁定事件手動(dòng)傳遞事件對(duì)象
如果加括號(hào)就需要手動(dòng)的傳遞事件對(duì)象
<div id="app">
<!-- 手動(dòng)傳遞事件對(duì)象,此時(shí)$event就是事件對(duì)象 -->
<button @click="reversed($event,123)">點(diǎn)擊</button>
</div>
<script>
const vm = new Vue({
el:"#app",
data:{
msg:"Hello Vue"
},
methods: {
reversed(ev,num){
console.log(ev) // 事件對(duì)象
console.log(num) // 123
}
}
})
</script>
點(diǎn)擊結(jié)果
5.4 默認(rèn)事件對(duì)象的變量
同時(shí)還發(fā)現(xiàn): 無(wú)論加不加括號(hào),傳不傳參數(shù),在函數(shù)里變量event
默認(rèn)是事件對(duì)象, 所以不要定義同名變量將其覆蓋就可以了
<div id="app">
<!-- 手動(dòng)傳遞事件對(duì)象,此時(shí)$event就是事件對(duì)象 -->
<button @click="reversed($event,123)">點(diǎn)擊</button>
</div>
<script>
const vm = new Vue({
el:"#app",
data:{
msg:"Hello Vue"
},
methods: {
reversed(ev,num){
console.log(event);
}
}
})
</script>
點(diǎn)擊顯示結(jié)果
總結(jié):
- 方法寫在methods屬性中
- 事件函數(shù)不需要傳參不加括號(hào), 需要傳參加括號(hào)
- 事件函數(shù)無(wú)括號(hào),默認(rèn)第一個(gè)參數(shù)是事件對(duì)象
- 事件函數(shù)有括號(hào),需要手動(dòng)傳遞事件對(duì)象
- 無(wú)論事件函數(shù)有無(wú)括號(hào),event變量都是事件對(duì)象,前提不能有同名變量覆蓋