- 事件的定义和消费
-
this.$on('my_events', this.handleEvents)
定义一个监听的(my_events)事件并指定他的执行对象/执行函数(this.handleEvents) -
this.$emit('my_events', 'my params')
消费这个事件 - 使用emit后,我们可以把事件的定义和消费实现逻辑的解耦,可以在父组件监听(
$on
)子组件中直接调用事件($emit
) - 要强调的一点是:
$on
和$emit
事件必须是在一个公共的实例上才能触发!!!- 我们可以使用一个空的 Vue 实例作为中央事件总线,比如首先在main.js里新加bus作为一个公共的实例
- 例:
<html>
<head>
<title>$emit 和 $on</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="root">
<button @click="boost">触发事件</button>
<!-- => hello vue my params -->
</div>
<script>
new Vue({
el: '#root',
data() {
return {
message: 'hello vue'
}
},
created() {
this.$on('my_events', this.handleEvents)
},
methods: {
handleEvents(e) {
console.log(this.message, e)
},
boost() {
this.$emit('my_events', 'my params')
}
}
})
</script>
</body>
</html>
Vue文档
$on
的介绍
vm.$on( event, callback )
参数:
{string | Array<string>} event (数组只在 2.2.0+ 中支持)
{Function} callback
用法:
监听当前实例上的自定义事件。事件可以由vm.$emit
触发。回调函数会接收所有传入事件触发函数的额外参数。
示例:
vm.$on('test', function (msg) {
console.log(msg)
})
vm.$emit('test', 'hi')
// => "hi"
$on
源码
Vue.prototype.$on = function (event, fn) {
var vm = this //Vue的实例
if (Array.isArray(event)) {
//判断是否是event为数组
for (var i = 0, l = event.length; i < l; i++) {
vm.$on(event[i], fn)
}
} else {
// 判断实例下是否包含了我们的传入的event,不包含则创建一个新的event数组并且第一个就是传入的fn方法(所以我们一个event可以有多个fn方法,我们会在emit时依次执行我们的fn方法
;(vm._events[event] || (vm._events[event] = [])).push(fn)
// optimize hook:event cost by using a boolean flag marked at registration
// instead of a hash lookup
if (hookRE.test(event)) {
vm._hasHookEvent = true
}
}
return vm
}
Vue文档emit( eventName, […args] )
参数:
{string} eventName
[...args]
触发当前实例上的事件。附加参数都会传给监听器回调。
$emit
的源码
//传入 my_events
Vue.prototype.$emit = function (event) {
var vm = this
{
var lowerCaseEvent = event.toLowerCase() //toLowerCase() 方法用于把字符串转换为小写。 ->my_events
if (lowerCaseEvent !== event && vm._events[lowerCaseEvent]) {
tip(
'Event "' +
lowerCaseEvent +
'" is emitted in component ' +
formatComponentName(vm) +
' but the handler is registered for "' +
event +
'". ' +
'Note that HTML attributes are case-insensitive and you cannot use ' +
'v-on to listen to camelCase events when using in-DOM templates. ' +
'You should probably use "' +
hyphenate(event) +
'" instead of "' +
event +
'".'
)
}
}
var cbs = vm._events[event] //处理的函数
if (cbs) {
cbs = cbs.length > 1 ? toArray(cbs) : cbs //判断cbs是否为数组
var args = toArray(arguments, 1) //arguments = ["my_events"=>事件名称,"my params"=>我们传入的参数],args = "my params"
var info = 'event handler for "' + event + '"'
for (var i = 0, l = cbs.length; i < l; i++) {
invokeWithErrorHandling(cbs[i], vm, args, vm, info) // 关键的逻辑使用 try catch 捕获异常,我们在抛出异常时也不会程序中断
}
}
return vm
}
案例可以参考同站的点击这里