vue.js의 부모에서 자식 메서드에 액세스하는 방법


91

두 개의 중첩 구성 요소가 있습니다. 부모에서 자식 메서드에 액세스하는 적절한 방법은 무엇입니까?

this.$children[0].myMethod() 트릭을 수행하는 것처럼 보이지만 매우 추악하지 않습니까? 더 나은 방법이 될 수 있습니다.

<script>
import child from './my-child'

export default {
  components: {
   child
  },
  mounted () {
    this.$children[0].myMethod()
  }
}
</script>

먼저, 정말로해야하는지 스스로에게 물어보십시오. 모든 페이지 상태가 상점에 있으면 부모-자식 통신이 필요하지 않습니다.
bbsimonbb

7
@bbsimonbb 상태는 이벤트와 다릅니다. 이것은 특히 상위에서 하위 이벤트를 트리거하는 것에 관한 것입니다. 또한 소품 다운 스트림을 전달하여 Vuex를 사용하는 모든 작업을 수행 할 수 있지만 이렇게하려면 자식 구성 요소가 변경 사항을 확인하기 위해 소품 / 저장소를 감시해야하므로 원하는 모든 작업을 수행 할 때 명백히 잘못된 데이터 변경 사항으로 RPC를 효과적으로 에뮬레이션 할 수 있습니다. 구성 요소에서 작업을 트리거합니다.
Bojan Markovic

답변:


244

ref 사용할 수 있습니다 .

import ChildForm from './components/ChildForm'

new Vue({
  el: '#app',
  data: {
    item: {}
  },
  template: `
  <div>
     <ChildForm :item="item" ref="form" />
     <button type="submit" @click.prevent="submit">Post</button>
  </div>
  `,
  methods: {
    submit() {
      this.$refs.form.submit()
    }
  },
  components: { ChildForm },
})

타이트 커플 링이 마음에 들지 않으면 @Yosvel Quintero에 표시된대로 Event Bus 를 사용할 수 있습니다 . 다음은 버스를 소품으로 전달하여 이벤트 버스를 사용하는 또 다른 예입니다.

import ChildForm from './components/ChildForm'

new Vue({
  el: '#app',
  data: {
    item: {},
    bus: new Vue(),
  },
  template: `
  <div>
     <ChildForm :item="item" :bus="bus" ref="form" />
     <button type="submit" @click.prevent="submit">Post</button>
  </div>
  `,
  methods: {
    submit() {
      this.bus.$emit('submit')
    }
  },
  components: { ChildForm },
})

구성 요소 코드.

<template>
 ...
</template>

<script>
export default {
  name: 'NowForm',
  props: ['item', 'bus'],
  methods: {
    submit() {
        ...
    }
  },
  mounted() {
    this.bus.$on('submit', this.submit)
  },  
}
</script>

https://code.luasoftware.com/tutorials/vuejs/parent-call-child-component-method/


38
이것은 실제 질문을 실제로 읽은 정답입니다. 선택한 답변은 실제로 반대 질문에 대답합니다 (하위 구성 요소에서 부모에 대한 메서드를 트리거하는 방법).
보얀 마코 빅

1
에 대한 링크 이벤트 버스 이 답변이 연결되는이 리디렉션되는 상태 관리 @bbsimonbb 읽고, 댓글을 그것 좀 이해.
Eido95

2
을 사용하는 경우 this.$refs.하위 구성 요소를 동적으로로드하면 안됩니다.
1_bug

감사합니다! 당신은 나에게 많은 문제를 구해주었습니다. 제작 문제를 고치고 필사적으로 답을 찾고있었습니다! <3
Osama Ibrahim

26

VueJS의 부모-자녀 통신

루트 Vue 인스턴스가를 통해 모든 하위 항목에 this.$root액세스 할 수 있으므로 부모 구성 요소는 this.$children배열을 통해 자식 구성 요소에 액세스 할 수 있고 자식 구성 요소 는를 통해 부모 구성 요소에 액세스 할 수 있습니다. this.$parent첫 번째 본능은 이러한 구성 요소에 직접 액세스하는 것입니다.

VueJS 문서는 특히 두 가지 이유 때문에 이에 대해 경고합니다.

  • 부모와 자녀를 단단히 연결합니다 (반대의 경우도 마찬가지).
  • 부모의 상태는 자식 구성 요소에 의해 수정 될 수 있으므로 신뢰할 수 없습니다.

해결책은 Vue의 맞춤 이벤트 인터페이스를 사용하는 것입니다.

Vue에서 구현 한 이벤트 인터페이스를 사용하면 구성 요소 트리에서 위아래로 통신 할 수 있습니다. 사용자 지정 이벤트 인터페이스를 활용하면 다음 네 가지 방법에 액세스 할 수 있습니다.

  1. $on() -이벤트를 수신 할 Vue 인스턴스에서 리스너를 선언 할 수 있습니다.
  2. $emit() -동일한 인스턴스 (자체)에서 이벤트를 트리거 할 수 있습니다.

$on()및 사용 예 $emit():

const events = new Vue({}),
    parentComponent = new Vue({
      el: '#parent',
      ready() {
        events.$on('eventGreet', () => {
          this.parentMsg = `I heard the greeting event from Child component ${++this.counter} times..`;
        });
      },
      data: {
        parentMsg: 'I am listening for an event..',
        counter: 0
      }
    }),
    childComponent = new Vue({
      el: '#child',
      methods: {
      greet: function () {
        events.$emit('eventGreet');
        this.childMsg = `I am firing greeting event ${++this.counter} times..`;
      }
    },
    data: {
      childMsg: 'I am getting ready to fire an event.',
      counter: 0
    }
  });
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.28/vue.min.js"></script>

<div id="parent">
  <h2>Parent Component</h2>
  <p>{{parentMsg}}</p>
</div>

<div id="child">
  <h2>Child Component</h2>
  <p>{{childMsg}}</p>
  <button v-on:click="greet">Greet</button>
</div>

원본 게시물에서 가져온 답변 : VueJS의 구성 요소 간 통신


1
감사합니다. 이벤트를 통해 내 코드를 상호 화해 보겠습니다!
al3x

5
내용을 복사 / 붙여 넣기 할 때 소스도 언급하는 것이 좋습니다.
Mihai Vilcu

17
이것은 아이에서 부모로의 의사 소통에 도움이됩니다. 그러나 부모에서 자녀에게 비슷한 방법이 있습니까? 예를 들어 사용자가 새 자식을 추가하도록 허용하기 전에 기존의 모든 항목이 유효성을 검사하기를 원합니다. 유효성 검사 논리가 자식에 있으므로 모든 항목을 살펴보고 예를 들어 validate () 메서드를 실행하고 싶습니다.
Mateusz Bartkowiak

66
이것은 실제로 요청 된 것과 반대되는 질문에 대한 대답입니다. Desmond Lua의 답변은 실제 질문에 대한 답변입니다.
보얀 마코 빅

4
이벤트 버스는 Chris Fritz의 vue antipatterns 목록에서 1 위 입니다. 이벤트 및 분산 상태로 모델링 할 수있는 모든 것은 전역 상태 및 양방향 바인딩으로 모델링 할 수 있으며 일반적으로 훨씬 나아질 것입니다.
bbsimonbb

1

컨트롤 렌더가 v-if. 그래서 저는 더 간단한 방법을 사용하기로 결정했습니다.

아이디어는 배열을 큐로 사용하여 호출해야하는 메서드를 자식 구성 요소에 보내는 것입니다. 구성 요소가 마운트되면이 대기열을 처리합니다. 새로운 메서드를 실행하기 위해 큐를 감시합니다.

(Desmond Lua의 답변에서 일부 코드 대여)

상위 구성 요소 코드 :

import ChildComponent from './components/ChildComponent'

new Vue({
  el: '#app',
  data: {
    item: {},
    childMethodsQueue: [],
  },
  template: `
  <div>
     <ChildComponent :item="item" :methods-queue="childMethodsQueue" />
     <button type="submit" @click.prevent="submit">Post</button>
  </div>
  `,
  methods: {
    submit() {
      this.childMethodsQueue.push({name: ChildComponent.methods.save.name, params: {}})
    }
  },
  components: { ChildComponent },
})

이것은 ChildComponent의 코드입니다.

<template>
 ...
</template>

<script>
export default {
  name: 'ChildComponent',
  props: {
    methodsQueue: { type: Array },
  },
  watch: {
    methodsQueue: function () {
      this.processMethodsQueue()
    },
  },
  mounted() {
    this.processMethodsQueue()
  },
  methods: {
    save() {
        console.log("Child saved...")
    },
    processMethodsQueue() {
      if (!this.methodsQueue) return
      let len = this.methodsQueue.length
      for (let i = 0; i < len; i++) {
        let method = this.methodsQueue.shift()
        this[method.name](method.params)
      }
    },
  },
}
</script>

그리고 processMethodsQueue믹스 인으로 이동 하는 것과 같은 개선의 여지가 많이 있습니다 .


0

자식 구성 요소를 다른 자식 구성 요소와 통신하기 위해 다음을 사용하여 자식에서 메서드를 호출하는 부모 메서드를 만들었습니다.

this.$refs.childMethod()

그리고 다른 아이로부터 루트 메서드를 호출했습니다.

this.$root.theRootMethod()

그것은 나를 위해 일했습니다.


이 답변이 부족 많은 설명을
수직 동기화
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.