コンポーネントの外部からVue.jsコンポーネントメソッドを呼び出す


229

子コンポーネントを持つメインVueインスタンスがあるとします。これらのコンポーネントの1つに属するメソッドをVueインスタンスの外部から完全に呼び出す方法はありますか?

次に例を示します。

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>

したがって、内部ボタンをクリックすると、increaseCount()メソッドはクリックイベントにバインドされて呼び出されます。イベントを外部ボタンにバインドする方法はありません。外部ボタンには、jQueryでリッスンしているクリックイベントがあるため、を呼び出す別の方法が必要になりますincreaseCount

編集

これはうまくいくようです:

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

ただし、子の配列内のインデックスでコンポーネントを参照しているため、これは適切なソリューションではありません。多くのコンポーネントでは、これが一定になりにくく、コードが読みにくくなります。


1
試してみたい場合は、mxinsを使用して回答を追加しました。私の意見では、この方法でアプリをセットアップすることを好みます。
オマールタンティ2018年

回答:


275

結局、Vueのrefディレクティブを使用することにしました。これにより、直接アクセスするためにコンポーネントを親から参照できます。

例えば

親インスタンスにコンポーネントを登録します。

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

参照付きのtemplate / htmlでコンポーネントをレンダリングします。

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

今、他の場所で外部からコンポーネントにアクセスできます

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

例については、このフィドルを参照してください:https : //jsfiddle.net/xmqgnbu3/1/

(Vue 1を使用した古い例:https : //jsfiddle.net/6v7y6msr/


6
それはおそらく定義していないからです。リンクされたフィドルを見てください。
ハリーグ2016年

29
webpackを使用している場合はvm、モジュールのスコープ方法が原因でアクセスできません。あなたのような何かをすることができwindow.app = vmますmain.js。出典:forum.vuejs.org/t/how-to-access-vue-from-chrome-console/3606
tw

1
このアプローチは通常と見なすことができますか?それともこれはハックですか?
CENT1PEDE 2017年

3
ハックと「通常の」コーディングの公式な定義はありますが、このアプローチをハックと呼ぶのではなく(または、同じことを達成するための「ハックの少ない」方法を探す)、なぜ必要なのかを質問する方が良いでしょう。この。多くの場合、Vueのイベントシステムを使用して外部コンポーネントの動作をトリガーしたり、コンポーネントを外部的にトリガーする理由を尋ねたりする方がよりエレガントな場合があります。
ハリーグ2017年

8
これは、ビューコンポーネントを既存のページに統合しようとしている場合に発生する可能性があります。ページ全体を再設計するのではなく、追加機能を段階的に追加するとよい場合があります。
アレン王

37

Vue2以降、これが適用されます:

var bus = new Vue()

//コンポーネントAのメソッド内

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

//コンポーネントBの作成されたフック内

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

  // ...
})

Vueのドキュメントについては、こちらをご覧ください。そして、ここではまさにこのイベントバスを設定する方法の詳細です。

プロパティ、イベント、および/または集中状態管理をいつ使用するかの詳細については、この記事を参照してください


1
短くて甘い!グローバルbus変数が気に入らない場合は、さらに一歩進んで、propsを使用してコンポーネントにバスを注入できます。私はvueが比較的新しいので、これが慣用的であることを保証することはできません。
byxor 2018

31

Vueイベントシステムを使用できます。

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

そして

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

ここにフィドルがあります:http : //jsfiddle.net/hfalucas/wc1gg5v4/59/


5
@GusDeCooLサンプルは編集されています。Vuejs 2.0以降、いくつかのメソッドが使用されなくなったわけではありません
Helder Lucas

1
コンポーネントの1つだけのインスタンスがある場合はうまく動作しますが、多くのインスタンスが存在する場合、より効率的に使用する$ refs.component.method()動作します
Koronos

22

受け入れられた回答の少し異なる(より単純な)バージョン:

親インスタンスにコンポーネントを登録します。

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

参照付きのtemplate / htmlでコンポーネントをレンダリングします。

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

コンポーネントメソッドにアクセスします。

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

22

子コンポーネントの参照を設定してから、親で$ refsを介して呼び出すことができます。

参照を子コンポーネントに追加します。

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

親にクリックイベントを追加:

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

var vm = new Vue({
  el: '#app',
  components: {
    'my-component': { 
      template: '#my-template',
      data: function() {
        return {
          count: 1,
        };
      },
      methods: {
        increaseCount: function() {
          this.count++;
        }
      }
    },
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  
  <my-component ref="childref"></my-component>
  <button id="external-button" @click="$refs.childref.increaseCount()">External Button</button>
</div>
  
<template id="my-template">
  <div style="border: 1px solid; padding: 2px;" ref="childref">
    <p>A counter: {{ count }}</p>
    <button @click="increaseCount">Internal Button</button>
  </div>
</template>


2
これまでで最もクリーンなソリューション。
grreeenn

すばらしい答えです。垂直方向に少し小さくなるようにhtmlを編集します。現在、実行すると「内部ボタン」しか表示されませんが、混乱を招く可能性があります。
Jesse Reza Khorasanee、

8

child_method()子コンポーネントにaがあるとします。

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

次にchild_method、親コンポーネントから実行します。

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

子コンポーネントから親コンポーネントメソッドを実行する場合:

this.$parent.name_of_method()

注:このように子コンポーネントと親コンポーネントにアクセスすることはお勧めしません。

代わりに、ベストプラクティスとして、親子のコミュニケーションに小道具とイベントを使用します。

コンポーネント間の通信が必要な場合は、必ずvuexまたはイベントバスを使用してください

この非常に役立つ記事を読んでください



はい、できますが、「ベストプラクティス」とは見なされません。下位は子の使用プロパティ、上位は親の使用イベントです。「側方」もカバーするには、カスタムイベント、またはvuexなどを使用します。詳細については、この素晴らしい記事参照してください。
musicformellons 2018

はい、お勧めしません。
roli roli

3

これは、他のコンポーネントからコンポーネントのメソッドにアクセスする簡単な方法です

// 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

私はそれが正しい方法であるかどうかわかりませんが、これは私にとってはうまくいきます。
最初に、コンポーネントで呼び出すメソッドを含むコンポーネントをインポートします

import myComponent from './MyComponent'

MyCompenentの任意のメソッドを呼び出します

myComponent.methods.doSomething()

これにより、コンポーネント内のデータにアクセスすることはできません。あなたの場合は doSomethingデータから任意のものを使用している、この方法は無用です。
cyboashu

-7

私は非常にシンプルなソリューションを使用しました。Vanilla JSを使用して、選択したVueコンポーネントにメソッドを呼び出すHTML要素を含め、クリックをトリガーします!

Vueコンポーネントには、次のようなものが含まれています。

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

私がバニラJSを使って使うこと:

const btnReload = document.querySelector('[data-id="btnReload"]');
btnReload.click();                

これは、特にOPの質問のコンテキストでは、vue内ではまったく良いプラクティスとは見なされません。
ハイブリッドWeb
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.