Call a Vue.js component method from outside the component

ghz 8months ago ⋅ 86 views

Let's say I have a main Vue instance that has child components. Is there a way of calling a method belonging to one of these components from outside the Vue instance entirely?

Here is an example:

var vm = new Vue({
  el: '#app',
  components: {
    'my-component': { 
      template: '#my-template',
      data: function() {
        return {
          count: 1,
        };
      },
      methods: {
        increaseCount: function() {
          this.count++;
        }
      }
    },
  }
});

$('#external-button').click(function()
{
  vm['my-component'].increaseCount(); // This doesn't work
});
<script src="http://vuejs.org/js/vue.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="app">
  
  <my-component></my-component>
  <br>
  <button id="external-button">External Button</button>
</div>
  
<template id="my-template">
  <div style="border: 1px solid; padding: 5px;">
  <p>A counter: {{ count }}</p>
  <button @click="increaseCount">Internal Button</button>
    </div>
</template>

So when I click the internal button, the increaseCount() method is bound to its click event so it gets called. There is no way to bind the event to the external button, whose click event I am listening for with jQuery, so I'll need some other way to call increaseCount.

EDIT

It seems this works:

vm.$children[0].increaseCount();

However, this is not a good solution because I am referencing the component by its index in the children array, and with many components this is unlikely to stay constant and the code is less readable.

Answers

To call a method belonging to a Vue component from outside the Vue instance, you can use Vue's component reference system. Instead of relying on the array index of vm.$children, you can assign a ref attribute to your component and access it using vm.$refs.

Here's how you can modify your code to achieve this:

<div id="app">
  <my-component ref="myComponent"></my-component>
  <br>
  <button id="external-button">External Button</button>
</div>
var vm = new Vue({
  el: '#app',
  components: {
    'my-component': { 
      template: '#my-template',
      data: function() {
        return {
          count: 1,
        };
      },
      methods: {
        increaseCount: function() {
          this.count++;
        }
      }
    },
  }
});

$('#external-button').click(function() {
  vm.$refs.myComponent.increaseCount();
});

In this code, I've added a ref="myComponent" attribute to the <my-component> tag. This assigns a reference to the component instance, which can be accessed using vm.$refs.myComponent. Then, in the jQuery click handler, I'm calling the increaseCount() method on the component instance using vm.$refs.myComponent.increaseCount().

This approach is more robust and readable compared to relying on the array index of vm.$children. It ensures that even if the order of components changes or additional components are added, the correct component reference is still used.