programing

vue.js에서 상위 메서드에 액세스하는 방법

iphone6s 2023. 10. 14. 09:54
반응형

vue.js에서 상위 메서드에 액세스하는 방법

중첩된 구성 요소가 두 개 있는데 부모로부터 자식 방법에 액세스하는 적절한 방법은 무엇입니까?

this.$children[0].myMethod()속임수를 쓰는 것처럼 보이지만 꽤나 추합니다. 그렇지 않습니까, 더 좋은 방법은 무엇일까요?

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

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

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처럼 이벤트 버스를 이용할 수 있습니다.아래는 버스를 타고 지나가는 이벤트 버스를 소품으로 사용하는 또 다른 예입니다.

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/

Vue 2.7Vue 3.2.x의 경우

<!-- Parent -->
<script setup>
import { ref, onMounted } from 'vue'
import ChildComponent from './components/ChildComponent.vue'

const childComponentRef = ref()

onMounted(() => {
    childComponentRef.value.doSomething()
})
</script>

<template>
    <ChildComponent ref="childComponentRef" />
</template>

스크립트 설정

<!-- Child -->
<script setup>
const doSomething = () => {
    console.log('Im batman')
}

defineExpose({
    doSomething
})
</script>

셋업기능

<!-- Child -->
<script>
import { defineComponent } from 'vue'

export default defineComponent({
    setup(props, context) {
        const doSomething = () => {
            console.log('Im batman')
        }

        context.expose({ doSomething })
    }
})
</script>

참고: 이런 행동은 피하고 컴포지트를 사용해야 합니다.구성 요소(타사 플러그인 등)를 제어할 수 없는 경우.

제안된 솔루션은 Vue 2용이지만, Vue 3 Composition API 솔루션을 찾는 경우 마이그레이션할 때 다음을 수행할 수 있습니다.

"doSomething" 메서드가 있는 템플릿의 자식 구성 요소:

 <div class="form">                                                                                                                                                        
      <child-component ref="childComponentRef" />                                                                      
</div>  

Vue 2 사용:

this.$refs.childComponentRef.doSomething( );
       

Vue 3 Composition Api 사용:

    setup( )
    {
        const childComponentRef = ref( );

        childComponentRef.value.doSomething( )

        return {
           childComponentRef
        }
     }  

VueJS에서의 부모-자녀 통신

는 를 모든 수 .this.$root 요소는 , 를 요소에 수 .this.$children배열, 자식 구성 요소는 다음을 통해 부모 구성 요소에 액세스할 수 있습니다.this.$parent은 이 .

VueJS 설명서는 다음과 같은 두 가지 매우 좋은 이유로 이에 대해 경고합니다.

  • 부모와 자녀를 긴밀하게 연결합니다(그리고 그 반대도 마찬가지입니다).
  • 부모의 상태는 자식 구성 요소로 수정할 수 있기 때문에 의존할 수 없습니다.

해결책은 뷰의 사용자 지정 이벤트 인터페이스를 사용하는 것입니다.

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의 구성 요소 간 통신

가 합니다의 을 받는 및 버스 가 발생합니다.v-if좀 더 그래서 좀 더 간단한 방법으로 진행하기로 했습니다.

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

(데스몬드 루아의 대답에서 코드를 빌리고 있음)

상위구성요소코드:

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

하위 구성요소 코드입니다.

<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...에 섞이게 됩니다.

mohgaderi의 답변이 마음에 드는데, 몇 가지 문제가 생겨서 그의 샘플 코드를 사용해서 제가 수정해야 할 부분을 보여드리겠습니다. (제 프로젝트에서는 Vue 3와 Options API를 사용하고 있습니다.)

Mohgaderi의 부모 구성 요소 코드와 내 변경 사항에 대한 참고 사항:

import ChildComponent from './components/ChildComponent'

new Vue({
  el: '#app',
  data: {
    item: {},
    childMethodsQueue: [],
  },
  // Note: In the template below, I added @child-methods-finished="childMethodsFinished" 
  //       as an event listener, so that we can reset the childMethodsQueue array to
  //       empty once the methods are finished.
  //       If you don't reset it, then the methods stay in there and cause problems.
  template: `
  <div>
     <ChildComponent :item="item" 
                     :methods-queue="childMethodsQueue"
                     @child-methods-finished="childMethodsFinished" />
     <button type="submit" @click.prevent="submit">Post</button>
  </div>
  `,
  methods: {
    submit() {
      this.childMethodsQueue.push({
        name: ChildComponent.methods.save.name,
        params: {}  // Note: delete the {} and put the name of your params, if you use a method that passes in params.
      })
    }
  },
  components: { ChildComponent },
})

Mohgaderi의 하위 구성 요소 코드와 내 변경 사항에 대한 참고 사항:

import { objectToString } from "@vue/shared"

export default {
    name: 'ChildComponent',
    props: {
      methodsQueue: { type: Array },
    },
    // Note:  I had to rewrite the watch option because it would not trigger.
    //        You have to add "deep, true" for arrays and objects.
    //        The function has to be called "handler" for it to work as well.
    watch: {
      methodsQueue: {
        handler() {
          this.processMethodsQueue()
        },
        deep: true,
      }
    },
    // Note:  Remove "mounted()" function if you don't want it to run on the mounted event.
    mounted() {
      this.processMethodsQueue()
    },
    methods: {
      save() {
          console.log("Child saved...")
      }, 
      processMethodsQueue() {
        if (!this.methodsQueue) return
        let len = this.methodsQueue.length

        if (!len) return  // Note:  This is required to prevent an infinite loop.
                          //        When we reset the childMethodsQueue array to empty,
                          //        it will trigger this method through the watch option,
                          //        so we need this in order to stop the cycle once we are done.

        // Note:  Instead of using ".shift()" to access an item in the array
        //        we need to use "[i]" otherwise we will get muliple calls of the method
        for (let i = 0; i < len; i++) {
          let method = this.methodsQueue[i]
          this[method.name](method.params)
        }

        // Note:  Now that we are done calling methods, we need to emit an event back to the parent
        //        so it can call it's method to reset the childMethodsQueue array to empty
        this.$emit('child-methods-finished')
      },
    },
  }

자식 구성 요소를 다른 자식 구성 요소와 통신하려면 부모에서 자식 구성 요소의 메서드를 호출하는 방법을 만들었습니다.

this.$refs.childRef.childMethod()

childRef는 자식 구성 요소 및 자식 구성 요소의 참조입니다. 메서드는 자식 구성 요소에 있는 모든 메서드로 대체할 수 있습니다.

그리고 또 다른 아이로부터 나는 루트 메소드라고 불렀습니다.

this.$root.theParentMethod() // It works with Bootstrap Vue
this.$parent.theParentMethod()

그것은 나에게 효과가 있었다.

언급URL : https://stackoverflow.com/questions/40957008/how-to-access-to-a-child-method-from-the-parent-in-vue-js

반응형