Llamar a un método de componente Vue JS desde fuera del componente


Digamos que tengo una instancia principal de Vue que tiene componentes secundarios. ¿Hay alguna forma de llamar a un método que pertenece a uno de estos componentes desde fuera de la instancia de Vue por completo?

Aquí hay un ejemplo:

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>

Así que cuando hago clic en el botón interno, el método increaseCount() está vinculado a su evento de clic por lo que se llama. No hay manera de vincular el evento al botón externo, cuyo evento de clic estoy escuchando con jQuery, así que necesitaré alguna otra manera para llamar increaseCount.

EDITAR

Parece Que esto funciona:

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

Sin embargo, esta no es una buena solución porque estoy haciendo referencia al componente por su índice en el array hijos, y con muchos componentes es poco probable que esto se mantenga constante y el código es menos legible.

Author: harryg, 2015-11-13

6 answers

Al final opté por usar la directiva ref de Vue. Esto permite hacer referencia a un componente desde el padre para acceso directo.

Por ejemplo

Tener un compenent registrado en mi instancia padre:

var vm = new Vue({
    el: '#app',
    components: { 'my-component': myComponent }
});

Renderiza el componente en template / html con una referencia:

<my-component ref="foo"></my-component>

Ahora, en otro lugar puedo acceder al componente externamente

<script>
vm.$refs.foo.doSomething(); //assuming my component has a doSomething() method
</script>

Vea este violín para un ejemplo: https://jsfiddle.net/xmqgnbu3/1 /

(antiguo ejemplo usando Vue 1: https://jsfiddle.net/6v7y6msr/)

 138
Author: harryg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-29 14:25:17

Puede usar el sistema de eventos Vue

vm.$broadcast('event-name', args)

Y

 vm.$on('event-name', function())

Aquí está el violín: http://jsfiddle.net/hfalucas/wc1gg5v4/59 /

 20
Author: Helder Lucas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-08 18:58:35

En Vue2 esto se aplica:

var bus = new Vue()

/ / en el método del componente A

bus.$emit('id-selected', 1)

/ / en el gancho creado del componente B

bus.$on('id-selected', function (id) {

  // ...
})

Ver aquí para los documentos del SDV. Y aquí hay más detalles sobre cómo configurar este bus de eventos exactamente.

Si desea más información sobre cuándo usar propiedades, eventos y/ o administración de estado centralizada, consulte este artículo.

 12
Author: musicformellons,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-31 14:42:51

Supongamos que tiene un componente hijo child_component:

<template>
  <h1>I am the child component</h1>
</template>

export default {
    name: 'child-component',
    methods: {
        child_method () {
            console.log('I got clicked')
        }
    }
}

Ahora desea ejecutar child_method desde el componente padre:

<template>
    <div>
        <button @click="exec">Execute child component</button>
        <child-cmp ref="child"></child_cmp>
    </div>
</template>

export default {
    name: 'parent-component',
    methods: {
        exec () {
            this.$refs.child.child_method() //execute the method belong to child
        }
    }
}

Si desea ejecutar un método de componente padre desde el componente hijo:

this.$parent.name_of_method()

NOTA: No se recomienda acceder a los componentes hijo y padre de esta manera. Si desea comunicación entre componentes seguramente use vuex o event bus


 0
Author: roli roli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-01 06:07:22

Aquí hay una simple

this.$children[indexOfComponent].childsMethodName();
 -1
Author: Pratik Khadtale,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-07 11:02:39

Esta es una forma sencilla de acceder a los métodos de un componente desde otro componente

// This is external shared (reusable) component, so you can call its methods from other components

export default {
   name: 'SharedBase',
   methods: {
      fetchLocalData: function(module, page){
          // .....fetches some data
          return { jsonData }
      }
   }
}

// This is your component where you can call SharedBased component's method(s)
import SharedBase from '[your path to component]';
var sections = [];

export default {
   name: 'History',
   created: function(){
       this.sections = SharedBase.methods['fetchLocalData']('intro', 'history');
   }
}
 -1
Author: Dotnetgang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-28 17:31:18