Bileşenin dışından bir Vue.js bileşen yöntemi çağırın


229

Diyelim ki alt bileşenleri olan bir ana Vue örneğim var. Bu bileşenlerden birine ait bir yöntemi Vue örneğinin dışından tamamen çağırmanın bir yolu var mı?

İşte bir örnek:

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>

Dahili düğmeyi tıkladığımda, increaseCount()yöntem click olayına bağlanır, böylece çağrılır. Olayı, jQuery ile dinlediğim tıklama olayını harici düğmeye bağlamak için bir yol yoktur, bu yüzden aramak için başka bir yola ihtiyacım olacak increaseCount.

DÜZENLE

Bu işe yarıyor gibi görünüyor:

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

Ancak, bu iyi bir çözüm değil çünkü ben çocuk dizindeki dizinine göre bileşen başvurmak ve birçok bileşen ile bu sabit kalmak olası değildir ve kod daha az okunabilir.


1
Denemek istiyorsanız mxins kullanarak bir cevap ekledim. Bence uygulamayı bu şekilde kurmayı tercih ediyorum.
Omar Tanti

Yanıtlar:


278

Sonunda Vue refdirektifini kullanmayı seçtim . Bu, bir bileşene doğrudan erişim için üst öğeden başvuruda bulunulmasına izin verir.

Örneğin

Ana örneğimde kayıtlı bir bileşen olsun:

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

Şablon / html'deki bileşeni bir başvuruyla oluşturun:

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

Şimdi, başka bir yerde bileşene harici olarak erişebiliyorum

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

Bir örnek için bu kemanı inceleyin: https://jsfiddle.net/xmqgnbu3/1/

(Vue 1 kullanan eski örnek: https://jsfiddle.net/6v7y6msr/ )


6
Çünkü muhtemelen tanımlamamışsınızdır. Bağlantılı kemana bak.
harryg

29
Web paketini kullanıyorsanız, modülleri kapsaması vmnedeniyle erişemezsiniz . Sen gibi bir şey yapabilirsiniz window.app = vmGözlerinde farklı main.js. Kaynak: forum.vuejs.org/t/how-to-access-vue-from-chrome-console/3606
tw airball

1
Bu yaklaşım normal kabul edilebilir mi? Yoksa bu bir hack mi?
CENT1PEDE

3
"Normal" kodlamaya neyin zarar verdiğine dair o kadar resmi bir tanım vardır, ancak bu yaklaşıma bir saldırı adı vermek yerine (ya da aynı şeyi elde etmenin "daha az hileli" bir yolunu aramak yerine) neden yapmanız gerektiğini sormak daha iyidir bu. Çoğu durumda, harici bileşen davranışını tetiklemek için Vue'nun olay sistemini kullanmak daha zarif olabilir, hatta bileşenleri neden harici olarak neden tetiklediğinizi sorabilirsiniz.
harryg

8
Bir görünüm bileşenini zaten var olan bir sayfaya entegre etmeye çalışıyorsanız bu durum ortaya çıkabilir. Sayfayı tamamen yeniden tasarlamak yerine, bazen aşamalı olarak ek işlevler eklemek güzeldir.
Allen Wang

38

Vue2'den beri bu geçerlidir:

var bus = new Vue()

// A bileşeninin yönteminde

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

// B bileşeninin oluşturduğu kancada

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

  // ...
})

Vue belgeleri için buraya bakın . Ve burada tam olarak bu olay otobüs ayarlamak konusunda daha fazla ayrıntı.

Mülkleri, olayları ve / veya merkezi durum yönetimini ne zaman kullanacağınız hakkında daha fazla bilgi edinmek istiyorsanız bu makaleye bakın .


1
Kısa ve güzel! Eğer küresel sevmediğim busdeğişkeni, Bir adım daha ileri gidip kullanarak bileşen içine otobüsü enjekte sahne . Vue için nispeten yeniyim, bu yüzden bunun deyimsel olduğunu garanti edemem.
byxor

31

Vue olay sistemini kullanabilirsiniz

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

ve

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

İşte keman: http://jsfiddle.net/hfalucas/wc1gg5v4/59/


5
@GusDeCooL örnek düzenlenmiştir. Vuejs 2.0'dan sonra kullanılan bazı yöntemlerin kullanımdan kaldırıldığı değil
Helder Lucas

1
Orada bileşenin sadece 1 örneğidir, ancak birçok örnek vardır eğer daha iyi kullanılması $ refs.component.method çalışırsa iyi çalışır ()
Koronos

22

Kabul edilen cevabın biraz farklı (daha basit) bir versiyonu:

Ana bileşene kayıtlı bir bileşen bulundurun:

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

Şablon / html'deki bileşeni bir başvuruyla oluşturun:

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

Bileşen yöntemine erişin:

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

22

Alt bileşenler için ref ayarlayabilir, ardından üst öğede $ refs yoluyla çağrı yapabilirsiniz:

Alt bileşene ref ekleyin:

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

Ebeveyne tıklama etkinliği ekle:

<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
şimdiye kadarki en temiz çözüm.
grreeenn

Mükemmel cevap. Html'yi dikey olarak biraz daha küçük olacak şekilde düzenleyeceğim. Şu anda sadece 'İç Düğme' görebildiğim zaman kafa karıştırıcı olabilir.
Jesse Reza Khorasanee

9

Alt child_method()bileşende bir tane olduğunu varsayalım:

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

Şimdi child_methodana bileşenden yürütmek istiyorsunuz :

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

Alt bileşenden bir üst bileşen yöntemi yürütmek istiyorsanız:

this.$parent.name_of_method()

NOT: Alt öğeye ve ana bileşene bu şekilde erişilmesi önerilmez.

Bunun yerine en iyi uygulama ebeveyn-çocuk iletişimi için Sahne ve Olaylar'ı kullanır.

Bileşenler arasında iletişim kurmak istiyorsanız, kesinlikle vuex veya olay veriyolu kullanın

Lütfen bu çok yararlı makaleyi okuyun



Evet, yapabilirsiniz, ancak 'en iyi uygulama' olarak kabul edilmez: Çocuk kullanım özelliklerine, Ebeveyn kullanım etkinliklerine doğru. Ayrıca 'yanları' kapsamak için özel etkinlikler kullanın veya örneğin vuex. Daha fazla bilgi için bu güzel makaleye bakın .
musicformellons

Evet, yapılması önerilmez.
roli roli

4

Bu, bir bileşenin yöntemlerine diğer bileşenlerden erişmenin basit bir yoludur

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

Bunun doğru yol olduğundan emin değilim ama bu benim için çalışıyor.
Önce bileşeninizde aramak istediğiniz yöntemi içeren bileşeni içe aktarın

import myComponent from './MyComponent'

ve sonra herhangi bir MyCompenent yöntemini çağırın

myComponent.methods.doSomething()

bu, bileşeninizdeki hiçbir veriye erişmenizi sağlamaz. eğer senin doSomethingverilerden herhangi bir şey kullanıyor, bu yöntem işe yaramaz.
cyboashu

-6

Çok basit bir çözüm kullandım. Seçtiğim Vue Bileşenime Vanilla JS kullanarak yöntemi çağıran bir HTML öğesi ekledim ve tıklamayı tetikliyorum!

Vue Bileşeninde aşağıdakine benzer bir şey ekledim:

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

Ben Vanilla JS kullanarak kullanmak:

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

Bu, özellikle OP'nin sorusu bağlamında, hiç de iyi bir uygulama olarak kabul edilmez.
Hibrit web geliştirici
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.