javascript - Hur man får åtkomst till en barnmetod från föräldern i vue.js


Jag har två inbäddade komponenter, vad är det rätta sättet att komma åt barnkomponenternas metoder från föräldern?

this.$children[0].myMethod() verkar fungera men det är ganska fult, eller hur, vad kan vara ett bättre sätt:

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

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

Svar #1

Du kan använda 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 },
})

Om du ogillar stark koppling kan du använda Event Bus som visas av @Yosvel Quintero. Nedan är ett annat exempel på att använda event bus genom att skicka in bus som 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 },
})

Komponentkod.

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

Svar #2

För Vue 2.7 och 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>

skriptinställning

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

defineExpose({
    doSomething
})
</script>

setup-funktion

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

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

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

Undvik detta så mycket som möjligt och använd komposabler. Om du inte har kontroll över komponenten (tredjepartsplugins, etc.) är undantaget.

Källa: https://vuejs.org/api/sfc-script-setup.html#defineexpose

Svar #3

Den föreslagna lösningen är för Vue 2, men om du hamnar här och letar efter en lösning för Vue 3 Composition API kan du göra följande vid migrering:

Ett barnkomponent i en mall, som har metoden "doSomething" :

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

Med Vue 2 :

this.$refs.childComponentRef.doSomething( );
       

Med Vue 3 Composition Api :

    setup( )
    {
        const childComponentRef = ref( );

        childComponentRef.value.doSomething( )

        return {
           childComponentRef
        }
     }  

Svar #4

Förälder-barn kommunikation i VueJS

Givet att en rot-Vue-instans är tillgänglig för alla ättlingar via this.$root, kan en föräldrakomponent komma åt barnkomponenter via this.$children-arrayen, och en barnkomponent kan komma åt sin förälder via this.$parent, kan din första instinkt vara att komma åt dessa komponenter direkt.

VueJS-dokumentationen varnar specifikt för detta av två mycket goda skäl:

  • Det binder föräldern hårt till barnet (och tvärtom)
  • Du kan inte lita på förälderns tillstånd, eftersom det kan ändras av en barnkomponent.

Lösningen är att använda Vues anpassade händelsegränssnitt

Händelsegränssnittet som implementeras av Vue gör att du kan kommunicera uppåt och nedåt i komponentträdet. Genom att utnyttja det anpassade händelsegränssnittet får du tillgång till fyra metoder:

  1. $on() - låter dig deklarera en lyssnare på din Vue-instans för att lyssna på händelser
  2. $emit() - låter dig utlösa händelser på samma instans (själv)

Exempel som använder $on() och $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>

Svar taget från originalinlägget: Kommunikation mellan komponenter i VueJS

Relaterade artiklar