컴포넌트 외부에서 Vue.js 컴포넌트 메소드 호출


229

자식 구성 요소가있는 기본 Vue 인스턴스가 있다고 가정 해 봅시다. 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를 사용하여 답변을 추가했습니다. 제 생각에는 앱을 이런 식으로 설정하는 것을 선호합니다.
Omar Tanti

답변:


275

결국 나는 Vue의 ref지시문 을 사용하기로 결정했습니다 . 이를 통해 직접 액세스 할 수 있도록 부모에서 구성 요소를 참조 할 수 있습니다.

예 :

부모 인스턴스에 compenent를 등록하십시오.

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
아마 당신이 그것을 정의하지 않았기 때문입니다. 연결된 바이올린을보십시오.
harryg

29
웹팩을 사용하는 경우 vm모듈 범위를 지정하는 방식으로 인해 액세스 할 수 없습니다 . 당신처럼 뭔가를 할 수 window.app = vm귀하의에서 main.js. 출처 : forum.vuejs.org/t/how-to-access-vue-from-chrome-console/3606
tw airball

1
이 접근법이 정상으로 간주 될 수 있습니까? 아니면 이것은 해킹입니까?
CENT1PEDE

3
해킹이란 무엇인가 대 "정상적인"코딩이란 무엇인가에 대한 공식적인 정의가 있지만,이 접근법을 해킹이라고 부르기보다는 (또는 같은 것을 달성하는 "덜 해킹 된"방법을 찾는 것) 왜해야하는지에 대한 질문을하는 것이 좋습니다 이. 대부분의 경우 Vue의 이벤트 시스템을 사용하여 외부 구성 요소 동작을 트리거하거나 구성 요소를 외부에서 전혀 트리거하는 이유를 묻는 것이 더 우아 할 수 있습니다.
harryg

8
뷰 컴포넌트를 이미 존재하는 페이지에 통합하려고 할 때 발생할 수 있습니다. 페이지를 완전히 다시 디자인하는 대신 때때로 기능을 추가로 추가하는 것이 좋습니다.
Allen Wang

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

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
component 인스턴스가 하나만있는 경우에는 잘 작동하지만 인스턴스가 많은 경우 $ 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 2019

좋은 대답입니다. html을 세로로 조금 작게 편집하려고합니다. 현재 혼란 스러울 수있는 '내부 버튼'만 볼 수 있습니다.
제시 레자 코라 사니

8

child_method()하위 구성 요소에 있다고 가정 해보십시오 .

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

예, 그렇게하지 않는 것이 좋습니다.
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

여기 간단한 것이 있습니다

this.$children[indexOfComponent].childsMethodName();

1

나는 그것이 올바른 방법인지 확실하지 않지만 이것은 나를 위해 일한다.
먼저 컴포넌트에서 호출하려는 메소드가 포함 된 컴포넌트를 가져 오십시오.

import myComponent from './MyComponent'

그런 다음 MyCompenent의 모든 메소드를 호출하십시오.

myComponent.methods.doSomething()

이렇게하면 구성 요소의 데이터에 액세스 할 수 없습니다. 당신이 경우 doSomething데이터에서 어떤 일을 사용하고,이 방법은 쓸모가 없다.
cyboashu

-7

나는 매우 간단한 해결책을 사용했습니다. Vanilla JS를 사용하여 선택한 Vue 구성 요소에 메소드를 호출하는 HTML 요소를 포함 시켰으며 클릭을 트리거합니다!

Vue Component에는 다음과 같은 내용이 포함되어 있습니다.

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

Vanilla JS를 사용하여 사용합니다.

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

이것은 특히 OP의 질문과 관련하여 Vue 내에서 좋은 습관으로 간주되지 않습니다.
하이브리드 웹 개발자
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.