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的觸發事件,可自定義觸發事件