目錄
一、綁定
二、解綁
組件自定義事件總結
TodoList案例對數據傳輸事件的修改
總結不易~ 本章節對我有很大收獲, 希望對你也是!!!
本章節素材已上傳Gitee:yihaohhh/我愛Vue - Gitee.com
前面我們學習的clikc、keyup……等一系列為js內置的事件(給HTML元素用的),現在我們就要學習組件的自定義事件(給組件用的!)!
一、綁定
現在想一個問題,把子元素傳給父元素有幾種辦法!
按照我們的進度, 現在只會通過props方法來得到App的函數然后進行傳參這一種辦法進行
那么現在就來介紹第二種辦法:組件自定義事件_綁定
- v-on:事件名="方法" 就是監聽子組件觸發的自定義事件。這個事件得由子組件用 $emit('事件名') 發出來。?
- 給誰綁定事件 就找誰觸發 ?給Student組件的實例對象
- 通過父組件給子組件綁定一個自定義事件實現:子給父傳遞數據 (第一種寫法 使用@或者v-on)
<!-- <Student v-on:atwhuc="getStudentName"/> --><Student @atwhuc="getStudentName"/>
大白話就是:“你每次喊一聲
atwhuc
,我就立刻執行getStudentName()
這個方法。你喊一次我就干一次,喊十次我就干十次。” 這個事件綁定在Student組件上
Student組件:
<template><div class="student"><h1>{{ msg }}</h1><h2>學生姓名:{{ name }}</h2><h2>學生性別:{{ sex }}</h2><button @click="sendStudentName">把學生名給App</button></div>
</template><script>
export default {name:'Student',data() {return {msg:'我是一個武漢傳媒學院的學生',name:'張三',sex: '男' }},methods: {sendStudentName() {// 觸發Student的實例身上的atwhuc事件 // 該事件被觸發 就讓給方法傳入了this.$emit('atwhuc', this.name, 666, 888, 999)}}}
</script><style scoped>.student {background-color: orange;padding: 5px;margin-top: 30px;}
</style>
這一種寫法是通過在子組件中觸發 $emit('atwhuc', 數據)
來發送一個自定義事件 'atwhuc'
,父組件通過 @atwhuc="方法"
監聽這個事件,從而實現父子組件之間的傳值和通信。
在子組件中用
$emit
是在向父組件發消息,這條消息就叫“自定義事件”。 有通知的意思
📌 補充說明(理解更深一點):
-
子組件不需要知道父組件的具體方法名,只管發事件(松耦合)。
-
父組件監聽這個事件并調用自己的方法,同時可以接收
$emit
傳來的數據。
但是這么直接用,有點局限性,我們可以更靈活一點!
?通過父組件給子組件綁定一個自定義事件實現:子給父傳遞數據 (第二種寫法 使用ref)
? ? <Student ref="student"/>
methods: {getSchoolName(name) {console.log('App收到了學校名', name)},getStudentName(name, ...params) {// params 是一個數組console.log('App被調用!', name, params)}},
// 放一個生命周期鉤子mounted() {// 靈活性強 setTimeout(() => {this.$refs.student.$on('atwhuc', this.getStudentName)}, 3000)this.$refs.student.$on('atwhuc', this.getStudentName) // 綁定自定義事件// 只觸發一次this.$refs.student.$once('atwhuc', this.getStudentName) // 綁定自定義事件(一次性)}
this.$refs.student:
- 就是你在 HTML 里寫的 <Student ref="student" />,
- 相當于你給這個組件起了個小名,方便后面找到它。
$on 當……時:
- $on('atwhuc', this.getStudentName):
- 是你在監聽這個組件有沒有“發出”一個叫 atwhuc 的信號。
- 如果發了,那就去執行 getStudentName 這個方法。
二、解綁
對于事件的解綁 也是通過實踐綁定來通過函數調用完成!
<button @click="unbind">解綁atwhuc事件</button>
unbind() {this.$off('atwhuc') // 只適用于解綁一個自定義事件// emitter.off 代替 $off// $on emitter.on// $emit emitter.emit}
可以發現this.$off? 只能進行單個事件的解綁
解綁多個事件,用一個數組進行存儲事件!
this.$off(['atwhuc', 'demo'])
更暴力的辦法, 全部都解綁!?
this.$off() // 全部都解綁
銷毀當前組件的全部實例
<button @click="death">銷毀當前Student組件的實例(vc)</button>
death() {this.$destroy() // 銷毀了當前的組件實例 銷毀后 所有Student實例的自定義事件全都不奏效了}
?本章節素材已上傳Gitee:yihaohhh/我愛Vue - Gitee.com?
組件自定義事件總結
想要把Student子組件的name傳給父組件 可以用函數來接受Student的name值, 然后更新App組件的studentName的值
這是可行的!
<h1>{{ msg }}, 學生姓名是:{{ studentName }}</h1>
getStudentName(name, ...params) {// params 是一個數組console.log('App被調用!', name, params),this.studentName = name},
this.$refs.student.$on('atwhuc', function(name, ...params) {console.log('App被調用!', name, params),this.studentName = name}) // 綁定自定義事件
用ref也是可行的!
<Student ref="student"/>mounted() {this.$refs.student.$on('atwhuc', this.getStudentName) // 綁定}
但是當我們將getStudentName注釋掉之后直接在生命周期鉤子里面寫回調函數發現this.studentName卻不能被賦值了!
this.$refs.student.$on('atwhuc', function(name, ...params) {console.log('App被調用!', name, params),this.studentName = name}) // 綁定自定義事件
點擊后不起作用,但是控制臺仍然會被執行!
那么我們就重新對this進行打印,來進行觀察!
this.$refs.student.$on('atwhuc', function(name, ...params) {console.log('App被調用!', name, params),console.log(this)this.studentName = name}) // 綁定自定義事件
能夠發現這些都是Student組件中才存在的, 只能說明 這個this就不是指向App組件的this ,而是Student組件的this
說明Vue的底層就是說明誰觸發了‘atwhuc’這個事件, 那么這個事件的回調就會指向誰
那么就說明當我們寫成箭頭函數的時候:這個this就又重新回到了App組件上
this.$refs.student.$on('atwhuc', (name, ...params)=> {console.log('App被調用!', name, params),console.log(this)this.studentName = name}) // 綁定自定義事件
那么組件可以用自定義事件,能不能用原生事件呢???點擊事件呢??
<Student ref="student" @click="show"/>
show() {alert(123)}
可以發現其實并沒效果! 原因就是這么寫Vue就自動默認把click當作是一個自定義事件,要觸發自定義事件,就必須要在Student組件上用$emit,就會進行觸發了!
sendStudentName() {// 觸發Student的實例身上的atwhuc事件 // 該事件被觸發 就讓給方法傳入了this.$emit('atwhuc', this.name, 666, 888, 999)this.$emit('demo') // 自定義事件名this.$emit('click')},
那么我們只需要添加一個修飾符,就可以讓Vue明白我們這是一種原生事件, .native
<Student ref="student" @click.native="show"/>
-
一種組件間通信的方式,適用于:<strong style="color:red">子組件 ===> 父組件</strong>
-
使用場景:A是父組件,B是子組件,B想給A傳數據,那么就要在A中給B綁定自定義事件(<span style="color:red">事件的回調在A中</span>)。
-
綁定自定義事件:
-
第一種方式,在父組件中:
<Demo @atguigu="test"/>
或<Demo v-on:atguigu="test"/>
-
第二種方式,在父組件中:
<Demo ref="demo"/>......mounted(){this.$refs.xxx.$on('atguigu',this.test)}
-
若想讓自定義事件只能觸發一次,可以使用
once
修飾符,或$once
方法。觸發自定義事件:
this.$emit('atguigu',數據)
-
-
解綁自定義事件
this.$off('atguigu')
-
組件上也可以綁定原生DOM事件,需要使用
native
修飾符。 -
注意:通過
this.$refs.xxx.$on('atguigu',回調)
綁定自定義事件時,回調<span style="color:red">要么配置在methods中</span>,<span style="color:red">要么用箭頭函數</span>,否則this指向會出問題!
?本章節素材已上傳Gitee:yihaohhh/我愛Vue - Gitee.com?
TodoList案例對數據傳輸事件的修改
對于子組件給父組件進行數據傳輸,就可以不在需要用props來傳遞一個函數,然后進行數據傳輸, 可以直接采用$emit來觸發父組件的自定義事件
那么同理,框起來的全部都是傳入的函數, 都是可以將props改寫為$emit來進行數據傳輸,而todos是一個數據不能修改為函數進行傳遞,就不能用$emit來進行修改
都可以換種方式來獲取自定義事件~