Digamos que tengo una de las principales de Vue instancia que tiene el niño de los componentes. Hay una manera de llamar a un método que pertenece a uno de estos componentes desde fuera de la Vue de instancia en su totalidad?

Aquí está un ejemplo:

JS:

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
});

HTML:

<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 increaseCount() método está vinculado a su evento click de lo que se llama. No hay manera de enlazar el evento en el exterior de botón, haga clic en cuyo caso estoy escuchando con jQuery, así que voy a necesitar alguna otra forma de llamar a increaseCount.

EDITAR

Parece que esto funciona:

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

Sin embargo, esta no es una buena solución porque estoy haciendo referencia a la componente por su índice en los niños de la matriz, y con muchos de los componentes de este es poco probable que permanezca constante y que el código es menos legible.

  • He añadido una respuesta usando mxins si quieres darle una oportunidad. En mi opinión prefiero el programa de instalación de la aplicación de esta manera.
InformationsquelleAutor harryg | 2015-11-12

9 Comentarios

  1. 222

    Al final he optado por usar Vue es ref directiva. Esto permite que un componente al que se hace referencia de los padres para el acceso directo.

    E. g.

    Tener un compenent registrado en la casa de mis padres instancia:

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

    Representar el componente de la plantilla html con una referencia:

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

    Ahora, en otros lugares me puede acceder al componente externamente

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

    Ver este violín por ejemplo: https://jsfiddle.net/xmqgnbu3/1/

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

    • no funciona, dice vm no está definido
    • Eso es porque probablemente no la define. Mira en los enlaces de violín.
    • Si usted está usando webpack, a continuación, usted no será capaz de acceder a vm debido a la forma en que los ámbitos de los módulos. Puedes hacer algo como window.app = vm en su main.js. Fuente: forum.vuejs.org/t/how-to-access-vue-from-chrome-console/3606
    • Realmente agradezco la explicación, gracias
    • Puede que este enfoque se considera como normal? O se trata de un hack?
    • Existe una definición oficial de lo que es un hack vs lo «normal» de la codificación, pero en lugar de llamar a este enfoque un hack (o buscar un «menos chapucero» forma de lograr la misma cosa) es probablemente mejor a la pregunta ¿por qué usted necesita hacer esto. En muchos casos puede ser más elegante para el uso de Vue de eventos del sistema para activar componente externo de comportamiento, o incluso preguntar por qué estás activación de componentes externamente en todos.
    • Esto puede suceder si usted está tratando de integrar un componente de vista en una página ya existente. En lugar de rediseño de la página en su totalidad, es agradable a veces de forma incremental agregar funcionalidad adicional.
    • Es un tipo de lo normal para Vue como se presta a la creación de bits de una manera sencilla sin tener que rehacer todo de tu html. Si usted necesita para hacer esto, es porque su estructura es ya bastante cuestionable; pero Vue funciona muy bien bajo cuestionable proyecto de diseños.
    • Yo lo he utilizado y funciona de maravillas. Es ideal para la creación de submódulos, de esa manera su vue archivo no se convierta en un desastre.
    • Gracias por tu sugerencia! No parece haber ninguna necesidad de registrar el componente (utilizando components: { 'my-component': myComponent }) en orden para que esto funcione. Es esta una diferencia en las versiones de Vue? O estoy haciendo algo inseguro si me lo dejo?
    • Tuve que usar esto. : esto.$refs.foo.doSomething();

  2. 27

    Puede utilizar Vue sistema de eventos

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

    y

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

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

    • ejemplo no funciona
    • el ejemplo ha sido editado. No es que después de Vuejs 2.0 algunos de los métodos utilizados no han sido censurados
    • Funciona bien si hay sólo 1 instancia de componente, pero si hay muchos casos, funciona mejor uso $refs.componente.método()
  3. 25

    Desde Vue2 esto se aplica:

    var bus = new Vue()

    //en componente del método

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

    //en el componente B se crea gancho

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

    Ver aquí para la Vue docs.
    Y aquí más detalles sobre cómo configurar este evento autobús exactamente.

    Si quieres más información sobre cuándo utilizar las propiedades, eventos y/o estado centralizado de gestión de ver este artículo.

    • Corto y dulce! Si no te gusta el mundial bus variable, puede ir un paso más allá e inyectar el autobús en el componente usando props. Soy relativamente nuevo en vue, así que no puedo asegurar que esto es idiomática.
  4. 8

    Un poco diferente (más simple) de la version aceptado respuesta:

    Tienen un componente registrado en la instancia primaria:

    export default {
        components: { 'my-component': myComponent }
    }

    Representar el componente de la plantilla html con una referencia:

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

    De acceso el método de componentes:

    <script>
        this.$refs.foo.doSomething();
    </script>
  5. 7

    Puede establecer ref para niño componentes, entonces los padres pueden llamar a través de $refs:

    Agregar ref infantil componente:

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

    Agregar haga clic en evento para padres:

    <button id="external-button" @click="$refs.childref.increaseCount()">External Button</button>

    JS:

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

    HTML:

    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
    <div id="app">
      
      <my-component ref="childref"></my-component>
      <br>
      <button id="external-button" @click="$refs.childref.increaseCount()">External Button</button>
    </div>
      
    <template id="my-template">
      <div style="border: 1px solid; padding: 5px;" ref="childref">
        <p>A counter: {{ count }}</p>
        <button @click="increaseCount">Internal Button</button>
      </div>
    </template>

    • la solución más limpia hasta el momento.
  6. 4

    Dicen que usted tiene un child_method() en el componente secundario:

    export default {
        methods: {
            child_method () {
                console.log('I got clicked')
            }
        }
    }

    Ahora quiere ejecutar el child_method de componente primario:

    <template>
        <div>
            <button @click="exec">Execute child component</button>
            <child-cmp ref="child"></child_cmp> <!-- note the ref="child" here -->
        </div>
    </template>
    
    export default {
        methods: {
            exec () { //accessing the child component instance through $refs
                this.$refs.child.child_method() //execute the method belongs to the child component
            }
        }
    }

    Si quieres ejecutar un componente principal método de infantil componente:

    this.$parent.name_of_method()

    NOTA: no se recomienda el acceso de los niños y padres de familia de componentes como esta.

    Lugar como mejor práctica de usar accesorios & Eventos para la comunicación padres-hijos.

    Si quiere que la comunicación entre los componentes seguramente vuex o bus de eventos

    Por favor, lea esta muy útiles artículo


    • Sí, se puede, pero no se considera la «mejor práctica»: hacia abajo para Niño utilizar las propiedades, hacia arriba para uso de Padres de eventos. Para cubrir también los ‘lateral’, el uso de eventos personalizados, o, por ejemplo, vuex. Ver este buen artículo para más información.
    • Sí, no es recomendable hacerlo.
  7. 3

    Esta es una forma sencilla de acceder a un componente de los métodos de otros componentes

    //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');
       }
    }
    • Usted es maldito de dios derecha +1
  8. -5

    He utilizado una solución muy simple. He incluido un elemento HTML que llama al método, en mi Vue Componente que yo seleccione, mediante la Vainilla JS, y yo gatillo clic!

    En la Vue Componente, he incluido algo como lo siguiente:

    <span data-id="btnReload" @click="fetchTaskList()"><i class="fa fa-refresh"></i></span>

    Que yo uso el uso de Vainilla JS:

    const btnReload = document.querySelector('[data-id="btnReload"]');
    btnReload.click();                
    • Esto no es considerado una buena práctica en todos los en vue, especialmente en el contexto de la OP de la pregunta.
    • podría ser una buena idea para explicar el por qué.

Dejar respuesta

Please enter your comment!
Please enter your name here