ค้นหาเว็บไซต์

javascript - วิธีเข้าถึงวิธีการลูกจากผู้ปกครองใน vue.js


ฉันมีคอมโพเนนต์ซ้อนสองอัน วิธีที่เหมาะสมในการเข้าถึงเมธอดของลูกจากผู้ปกติคืออะไร?

this.$children[0].myMethod() ดูเหมือนจะทําได้ดี แต่มันค่อนข้างน่าเกลียดใช่ไหม

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

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

คำตอบ #1

คุณสามารถใช้เอกสารอ้างอิงได้

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

ถ้าคุณไม่ชอบการเชื่อมโยงที่แน่นหนา คุณสามารถใช้ Event Bus ตามที่ @Yosvel Quintero แสดง ด้านล่างเป็นตัวอย่างอีกตัวอย่างหนึ่งของการใช้ Event Bus โดยการส่ง bus เข้ามาเป็น props

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/

คำตอบ #2

สำหรับ Vue 2.7 และ Vue 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>

หลีกเลี่ยงปัญหานี้ให้มากที่สุดและใช้องค์ประกอบ เว้นแต่คุณจะไม่สามารถควบคุมส่วนประกอบได้ (ปลั๊กอินของบุคคลที่สาม ฯลฯ)

แหล่งที่มา: https://vuejs.org/api/sfc-script-setup.html#defineexpose

คำตอบ #3

วิธีแก้ปัญหาที่แนะนำสำหรับ 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
        }
     }  

คำตอบ #4

การสื่อสารระหว่างผู้ปกครองและลูกใน VueJS

เมื่อมีการเข้าถึงอินสแตนซ์รากของ Vue ได้โดยลูกหลานทั้งหมดผ่าน this.$root คอมโพเนนต์พ่อแม่สามารถเข้าถึงคอมโพเนนต์ลูกผ่านอาร์เรย์ this.$children และคอมโพเนนต์ลูกสามารถเข้าถึงพ่อแม่ของมันผ่าน this.$parent สัญชาตญาณแรกของคุณอาจเป็นการเข้าถึงคอมโพเนนต์เหล่านี้โดยตรง

เอกสารของ VueJS เตือนเกี่ยวกับเรื่องนี้โดยเฉพาะด้วยเหตุผลที่ดีสองประการ:

  • มันเชื่อมพ่อแม่เข้ากับลูกอย่างแน่นหนา (และในทางกลับกัน)
  • คุณไม่สามารถพึ่งพาสถานะของพ่อแม่ได้ เนื่องจากสามารถถูกแก้ไขโดยคอมโพเนนต์ลูก

วิธีแก้ปัญหาคือการใช้ส่วนติดต่อเหตุการณ์แบบกำหนดเองของ Vue

อินเทอร์เฟซเหตุการณ์ที่ Vue นำไปใช้นั้นช่วยให้คุณสื่อสารขึ้นและลงในต้นไม้ของคอมโพเนนต์ การใช้ประโยชน์จากอินเทอร์เฟซเหตุการณ์แบบกำหนดเองจะให้คุณเข้าถึงสี่วิธีได้:

  1. $on() - ช่วยให้คุณประกาศตัวฟัง (listener) บนอินสแตนซ์ Vue ของคุณเพื่อฟังเหตุการณ์
  2. $emit() - อนุญาตให้คุณเรียกใช้งานอีเวนต์บนอินสแตนซ์เดียวกัน (self)

ตัวอย่างการใช้ $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

บทความที่เกี่ยวข้อง