故事还是得从$emit说起,某一天翻文档的时候看到$emit的说明
触发当前实例上的事件?就是自身组件上的事件呗,在父子组件通信中,父组件通过props传递给子组件数据(高阶组件可以用provide和inject),由于这是单向数据流,为了保证复用组件的的时候出现数据错乱。
那么只能通过在子组件里面去触发一个事件,来让父组件自己更新数据。
那么问题来了,$emit不是说好的触发当前实例上的事件吗?那是怎么去能触发父组件数据更新的呢?难道父组件里也能$on对应的事件???
其实不是的,看下面这个示例
<div id="app1"> <m-area :v="value" @do="pAdd"></m-area> </div> <script src="js/vue.js"></script> <script> Vue.component(‘mArea‘, { props: [‘v‘], template: ` <div> <button @click="add">{{v}}</button> </div> `, methods: { add() { this.$emit(‘do‘); console.log(this.v) } } }); let app1 = new Vue({ el: ‘#app1‘, data: { value: 1 }, methods: { pAdd() { this.value++; }, mouseover() { console.log(this.value); } } }); </script>
其实Button 的add方法是只触发了它自身的do事件,但是
<div id="app1"> <m-area :v="value" @do="pAdd"></m-area> </div>
mArea标签就是该组件啊,do事件是只触发了自身的事件,但是m-area标签是暴露在父组件里的,看看pAdd方法,它是父组件的mthods里的一个方法。由此刚好触发自身组件事件的时候,又触发了父组件里的一个方法,数据可以传参,最终达到更新父组件数据的目的。
接下来说说eventBus
一般都是创建一个bus.js,然后 export default new Vue()
其实背后就是个原理,通过bus.$emit然后涉及到原型链查找,相当于直接是针对于根组件App执行的$emit和$on,站在一个上帝视角,最顶层的组件上,就能形成一个事件总线,这样不同的兄弟组件之间就能进行通信了。
顺便可以看看vue-bus这个插件的源码,其实也是这么实现的,然后是通过更改get,改了一下调用属性方法的别名而已,然后挂到vue.prototype上,方便全局调用。
/** * vue-bus v1.1.0 * https://github.com/yangmingshan/vue-bus * @license MIT */ (function (global, factory) { typeof exports === ‘object‘ && typeof module !== ‘undefined‘ ? module.exports = factory() : typeof define === ‘function‘ && define.amd ? define(factory) : (global.VueBus = factory()); }(this, (function () { ‘use strict‘; function VueBus(Vue) { var bus = new Vue(); Object.defineProperties(bus, { on: { get: function get() { return this.$on } }, once: { get: function get() { return this.$once } }, off: { get: function get() { return this.$off } }, emit: { get: function get() { return this.$emit } } }); Vue.bus = bus; Object.defineProperty(Vue.prototype, ‘$bus‘, { get: function get() { return bus } }); } if (typeof window !== ‘undefined‘ && window.Vue) { window.Vue.use(VueBus); } return VueBus; })));
原文地址:https://www.cnblogs.com/hjj2ldq/p/9570269.html
时间: 2025-01-08 12:22:17