Vue components communication

前端 未结 6 1360
臣服心动
臣服心动 2020-12-01 09:18

I have two Vue components:

Vue.component(\'A\', {});

Vue.component(\'B\', {});

How can I access component A from component B? How does the

相关标签:
6条回答
  • 2020-12-01 09:36

    In addition to pesla' answer take a look at the guide's State Management section under Building large scale apps: http://vuejs.org/guide/application.html#State_Management . I've created a jsfiddle based on that here: https://jsfiddle.net/WarwickGrigg/xmpLg92c/.

    This technique works for components too: parent-child, sibling-sibling component relationships etc.

    var hub = {
      state: {
        message: 'Hello!'
      }
    }
    
    var vmA = new Vue({
        el: '#appA',
        data: {
          pState: {
            dA: "hello A" 
        },
        hubState: hub.state
      }
    })
    
    var vmB = new Vue({
        el: '#appB',
        data: {
          pState: {
            dB: "hello B"
        },
        hubState: hub.state
      }
    })
    
    0 讨论(0)
  • 2020-12-01 09:37

    Cross-component communication doesn't get much attention in the Vue.js docs, nor are there many tutorials that cover this subject. As components should be isolated, you should never "access" a component directly. This would tightly couple the components together, and thats exactly what you want to prevent doing.

    Javascript has an excellent method for communication: events. Vue.js has a built-in event system, mainly used for parent-child communication. From the docs:

    Although you can directly access a Vue instance’s children and parent, it is more convenient to use the built-in event system for cross-component communication. It also makes your code less coupled and easier to maintain. Once a parent-child relationship is established, you can dispatch and trigger events using each component’s event instance methods.

    Their example code to illustrate the event system:

    var parent = new Vue({
      template: '<div><child></child></div>',
      created: function () {
        this.$on('child-created', function (child) {
          console.log('new child created: ')
          console.log(child)
        })
      },
      components: {
        child: {
          created: function () {
            this.$dispatch('child-created', this)
          }
        }
      }
    }).$mount()
    

    Dan Holloran has recently written a piece on his "struggle" with cross-component messaging, in two pieces. This might be helpful to you if you need communication between components that have no parent-child relationship.

    Another approach I have experience with (other than using events for communication), is using a central component registry that has a reference to the public API with an instance of a component bound to it. The registry handles requests for a component and returns its public API.

    In the context of Vue.js, events would by my weapon of choice.

    0 讨论(0)
  • 2020-12-01 09:42

    Communicate between two Vuejs components has many options. If your components are parent and child then you should use "props" to send data from parent to child and use "events" to communicate from child to parent. If your components are sibling then you need to use "store" else you can use "$root" property.

    Parent to child

    parent component

    <ChildComponent :propsData="dataToPassToChild" />
    

    child component must have property

    props: ['propsData']
    

    Child to Parent

    child component

    this.$emit('messegeToParent', arg1, arg2, ...);
    

    parent component

    <ChildComponent @messageToParent="messageReceivedFromChild" />
    

    The below method should be in child component

    messageReceivedFromChild(arg1, arg2, ...) {
    
    }
    

    Sibling components

    component 1

    this.$root.$emit('message1', arg1, arg2, ...);
    

    component 2

    this.$root.$on('message1', (arg1, arg2, ...) => {
    
    });
    
    0 讨论(0)
  • 2020-12-01 09:45

    For sibling to sibling communication, I found using the parent as an event bus made the logic fairly trivial. Using $root as an event bus meant additional code to check the scope of components that may not be direct siblings. Using the $parent means that the scope of the events emitted can be controlled.

    The following example is for a TableHeader component. When clicked it re-orders the data in a table, other headers are no longer active and should not be displayed as such, a computed property cssClass is used for this.

    export default {
        name: 'TableHeader',
        props: ['sort'],
        data() {
            return {
                direction: this.sort
            }
        },
        computed: {
            cssClass() {
                if (this.direction === 'none') return '';
                return (this.direction === 'descending') ? 'headerSortUp': 'headerSortDown';
            }
        },
        methods: {
            clickHeader(event) {
                this.direction = (this.direction === 'none' || this.direction === 'descending') ? 'ascending' : 'descending';
    
                //We use the parent as an event bus
                this.$parent.$emit('TableHeader:sortChanged', this);
            },
            sortChanged(element) {
                //Dont reset if this is the emitter         
                if (this === element) return; 
    
                this.direction = 'none';
            }
        },      
        created() {
            this.$parent.$on('TableHeader:sortChanged', this.sortChanged);
        },
        beforeDestroy: function () {
            this.$parent.$off('TableHeader:sortChanged', this.sortChanged)
        }
    }
    
    0 讨论(0)
  • 2020-12-01 10:01

    Communication between the components can also be established by creating a single global event hub in your Vue application. Something like this:-

    var bus = new Vue();

    Now you can create custom events and listen to them from any component.

         // A.vue
        // ...
        doThis() {
            // do the job
    
            bus.$emit('done-this');
        }
    
        // B.vue
        // ...
           method:{
                 foo: function()
              }
        created() {
            bus.$on('done-this', foo);
        }
    

    More about this can be found from official documentation..

    0 讨论(0)
  • 2020-12-01 10:01

    It's best practice to use props and events.

    There are many examples online, like:

    • https://vuejs.org/v2/guide/components.html
    • https://alligator.io/vuejs/component-communication

    I recommend some reading on the topic.

    If the components are siblings and have no parent-child relationship it might be worth checking the architecture of your app.

    • Do A and B have a parent child relationship?
    • Is there a component C that is possibly the parent of A and B?

    If A and B are children of C, consider using props and events. Another way is to use props and sync, which can be helpful for form data:

    • https://medium.com/front-end-hacking/vues-v-model-directive-vs-sync-modifier-d1f83957c57c
    0 讨论(0)
提交回复
热议问题