Vue.prototype.$on = function (event, fn) { const hookRE = /^hook:/ //檢測自定義事件名是否是hook:開頭 const vm = this if (Array.isArray(event)) { // 如果第一個參數是數組 for (let i = 0; i < event.length; i++) { this.$on(event[i], fn) // 遞歸 } } else { (vm._events[event] || (vm._events[event] = [])).push(fn) // 如果有對應事件名就push,沒有創建為空數組然后push if (hookRE.test(event)) { // 如果是hook:開頭 vm._hasHookEvent = true // 標志位為true } } return vm }
Vue.prototype.$emit = function (event) { const vm = this let cbs = vm._events[event] // 找到事件名對應的回調集合 if (cbs) { const args = toArray(arguments, 1) // 將附加參數轉為數組 for (let i = 0; i < cbs.length; i++) { cbs[i].apply(vm, args) // 挨個執行對應的回調集合 } } return vm }
在組件(當前組件實例)的$on和$emit的執行原理:
$on往當前組件實例的事件中心(this._events)添加自定義事件
$emit在事件中心找到對應的自定義事件后調用事件
父子組件通過@傳遞事件詳解:
父組件在編譯模板后將子組件(@自定義事件="回調")的自定義事件及其回調通過$on添加到子組件的事件中心(this._events)
vue的$emit和$on特性可用於同級組件的傳信(如果不想使用vuex可采用此方法)
同級組件傳信原理:
<template> <div> <p @click='emit'>{{msg}}</p> </div> </template> <script> export default { name: 'demo', data () { return { msg : '點擊后派發事件' } }, created () { this.$on('wash_Goods',(arg)=> { console.log(arg) }) }, methods : { emit () { this.$emit('wash_Goods',['fish',true,{name:'vue',verison:'2.4'}]) } } } </script>
當點擊時可以調用wash_Goods這個事件,
如果在同級組件之間都引用一個名為bus.js
// bus.js
const Vue import 'vue' export default new Vue()
要通信的每個組件都引用
import Bus from ./bus.js
然后就可以通過Bus.$on('事件名', 事件)添加事件和Bus.$emit('事件名', 參數)來進行相互通信了