VUE中 $on, $emit, v-on三者關系
每個vue實例都實現了事件借口
- 使用$on(eventName)監聽事件
- 使用$emit(eventName)觸發事件
若把vue看成家庭(相當於一個單獨的components),女主人一直在家里派($emit)男人做事,而男人一直監聽$on着女主人的指派($emit)里eventName所觸發的事件消息,一旦$emit事件一觸發,$on則監聽$emit所派發的事件,派發的命令和執行所要做的事都是一一對應的
Vm.$emit(event,[...args])
參數 {String}event
[...args]
觸發當前實例上的事件,附加參數都會傳給監聽器回調
Vm.$on(evnet,callback)
參數 {String | Array<String>}event
{function}callback
監聽當前實例上的自定義事件,事件可以由Vm.$emit觸發,回調函數會接受所有傳入事件觸發函數的額外參數
第二個參數則是一個function,同樣也被叫做之前回調函數,里面可以接受到$emit觸發時所傳入的參數
<template>
<div>
<p @click="emit">{{msg}}</p>
</div>
</template>
<script>
export default {
data(){
return {
msg:'點擊后女人派發事件'
}
},
create(){
//派發wash_foods事件
this.$on('wash_foods',arg=>{
console.log(arg);
})
},
methods:{
emit(){
//觸發 wash_foods 事件
this.$emit('wash_foods',['fish','potato','fruit'])
}
}
}
</script>
當女人派發的事情多了,男人也會覺得很煩,聽到事件后,總會抱怨幾句,若女人在組成家庭之前,告訴男人將要監聽哪些事情,如果做一件抱怨一次,豈不是多此一舉,所以通過Array<String>event 把事件名寫成一個數組,在數組里寫入所要監聽的事件
<template>
<div>
<p @click="emit">{{msg}}</p>
<p @click="emitOther">{{msg2}}</p>
</div>
</template>
<script>
export default {
data(){
return {
msg:"點擊后女人派發事件",
msg2:"點擊后女人派發事件2"
}
},
create(){
this.$on(['wash_foods','driver_car'],arg=>{
console.log('事真多');
});
this.$on('wash_foods',arg=>{
console.log(arg)
});
this.$on('ariver_car',arg=>{
console.log(arg)
})
},
methods:{
emit(){
this.$emit('wash_foods','fish')
},
emitOther(){
this.$emit('driver_car',['audi','BWM'])
}
}
}
</script>
通常在寫組件的時候,讓 $emit在父級作用域中進行一個觸發,通知子組件 進行執行事情
自定義事件可以用來創建自定義的表單輸入組件
使用v-mode來進行數據雙向綁定
<input v-mode="sth">
//不過是以下事例的語法糖
<input v-bind:value="sth"
v-on:input="sth" = $event.target.value">
每當輸入框內容發生變化的時候,就會觸發input事件,然后把input輸入框中的value值再次傳遞給sth,此時value運用在一個input元素上,用 v-bind:value="sth" 意義上面只是把一一對應的雙向綁定,這就像一個循環操作,當再次觸發input事件時,input($event.target)對象中的value值會再次改變sth
通過自定義事件讓v-mode進行一個父子組件 雙向綁定的花
- v-bind:value="sth" 此時value是作為子組件接受props
接受的只能是value,因為v-model是基於input輸入框定制的,其中value值是input內部定制的
此時作用域在組件上時,v-on監聽的語法糖也會有所改變,監聽的並不是$event.target.value,而是回調函數的第一個參數
v-on:input = "sth = arguments[0]"
這是一個模態框的基本雛形,可以在父組件中通過v-model 來進行model框和父組件之間的顯示交互,通過子組件看出通過props接受了value值; 當點關閉的時候還是通過$emit事件觸發input事件,然后通過出入false參數
父組件隱式 v-on:input = "sth = arguments[0]"進行了監聽,一旦input事件觸發, 父組件就會進行監聽回調,從而雙向綁定
checkbox 和radio 原理
<input type="checkbox" :checked="status" @change="status=$event.target.checked"/> <input type="radio" :check="status" @change="status=$event.target.checked"/>
通過綁定checked屬性,同樣的監聽的是change事件,無論是checkbox還是radio在操作的時候都會隱式自動觸發一個change事件,跟input通過value值input觸發事件原理綁定是一樣的
<!-- 父組件 -->
<template>
<div class="Father">
<button @click="show=true">打開model</button>
<Son v-model="show"></Son>
</div>
</template>
<script>
import Son from './Son'
export default {
name:"Father",
data(){
return{
show:false
}
},
components:{son}
}
</script>
<!-- 子組件 -->
<template>
<div class="Son" v-show="value">
<div>
<p>model框</p>
<input type="text" v-model="value" />>
{{value}}
<button @click="close">關閉model</button>
</div>
</div>
</template>
<script>
export default {
name:'Son',
props:['value'], //接受父組件傳來的value值
methods:{
close(){//頁面關閉子組件model框按鈕事件
this.$emit('input',false)
}
}
}
</script>
定義組件v-model
定制組件,就可以重寫v-model里的props和event
默認情況下一個組件的v-model會使用value 屬性和input 事件,而value值被占用了,
或者表單和自定義v-model的$emit('input')事件發生沖突,為了避免這種沖突,可以定制組件v-model
input中的v-model和model顯示操作數據共同占用props中的value,同樣兩者也共同占據了emit('input' )觸發事件,input輸入框的事件自動觸發,而model顯示消失是手動觸發的
初始化的時候,input輸入框的值會被value傳入的false值給自動加上,當改變input輸入框的時候,因為沖突而導致報錯
定制v-model,通過model選項改變props和evnet的值,從而解除兩者的沖突
- props代替掉原本value的值,可以自定義值
- event代表掉原來input的觸發事件,可自定義觸發事件
