Vue.js में माता-पिता से बाल विधि तक कैसे पहुंचें


97

मेरे पास दो नेस्टेड घटक हैं, माता-पिता से बच्चे के तरीकों तक पहुंचने का उचित तरीका क्या है?

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 का अनुकरण कर सकें, जो कि केवल सादे गलत है जब आप चाहें घटक में एक क्रिया ट्रिगर।
बोजान मार्कोविच

जवाबों:


253

आप रेफ का उपयोग कर सकते हैं ।

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/


39
यह सही उत्तर है, कि वास्तव में वास्तविक प्रश्न पढ़ें। चयनित उत्तर वास्तव में विपरीत प्रश्न का उत्तर देता है (बच्चे के घटक से माता-पिता पर एक विधि को कैसे ट्रिगर किया जाए)।
बोजन मार्कोविच

1
इवेंट बस का लिंक जो इस उत्तर को लिंक कर रहा है, स्टेट मैनेजमेंट को पुनर्निर्देशित कर रहा है , @bbsimonbb टिप्पणी पढ़ने के बाद , इसके थोड़े समझ में आता है।
Eido95

2
यदि आप उपयोग करते हैं तो यह उल्लेख के लायक है this.$refs., आपको गतिशील रूप से बाल घटक को लोड नहीं करना चाहिए।
1_बग

धन्यवाद महोदय! आपने मुझे बहुत परेशानी से बचाया। मैं एक प्रोडक्शन मुद्दे को ठीक कर रहा था और सख्त जवाब तलाश रहा था! <3
ओसामा इब्राहिम

this.$ref.refएक सरणी वापस करने के लिए लगता है। तो मेरे लिए this.$refs.ref[0].autofocus();काम किया
जोज़ेफ़ प्लाटा

26

VueJS में जनक-बाल संचार

एक रूट Vue उदाहरण के माध्यम से सभी वंशज द्वारा सुलभ है this.$root, एक मूल घटक this.$childrenसरणी के माध्यम से बच्चे के घटकों का उपयोग कर सकते हैं, और एक बच्चा घटक के माध्यम से अभिभावक तक पहुँच सकते हैं this.$parent, आपकी पहली वृत्ति सीधे इन घटकों का उपयोग करने के लिए हो सकता है।

VueJS प्रलेखन इसके खिलाफ विशेष रूप से दो बहुत अच्छे कारणों के लिए चेतावनी देता है:

  • यह बच्चे को माता-पिता को कस कर देता है (और इसके विपरीत)
  • आप माता-पिता की स्थिति पर भरोसा नहीं कर सकते, यह देखते हुए कि यह एक बच्चे के घटक द्वारा संशोधित किया जा सकता है।

समाधान Vue के कस्टम इवेंट इंटरफ़ेस का उपयोग करना है

Vue द्वारा कार्यान्वित इवेंट इंटरफ़ेस आपको घटक ट्री को ऊपर और नीचे संचार करने की अनुमति देता है। कस्टम ईवेंट इंटरफ़ेस का लाभ उठाने से आपको चार विधियों तक पहुँच मिलती है:

  1. $on() - आप अपने वीयू उदाहरण पर एक श्रोता की घोषणा करने की अनुमति देता है जिसके साथ घटनाओं को सुनने के लिए
  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 10

5
जब सामग्री को कॉपी / पेस्ट करना स्रोत का उल्लेख करना अच्छा है।
मिहाई विलकू

17
यह बच्चे से माता-पिता तक संचार में सहायक है। लेकिन क्या माता-पिता से बच्चे तक ऐसा करने का कोई तरीका है? जैसे कि इससे पहले कि मैं उपयोगकर्ता को नए बच्चे को जोड़ने की अनुमति देता हूं, मैं चाहता हूं कि सभी मौजूदा लोगों को मान्य किया जाए - सत्यापन तर्क बच्चे में है, इसलिए मैं उन सभी के माध्यम से जाना चाहता हूं और उदाहरण के लिए मान्य () विधि को निष्पादित करता हूं।
माटूस बर्टकोविएक

68
यह विपरीत प्रश्न का उत्तर देता है कि वास्तव में क्या पूछा गया था। डेसमंड लुआ का उत्तर वास्तविक प्रश्न का उत्तर देता है।
बोजन मार्कोविच

4
इवेंट बस # 1 पर क्रिस फ्रिट्ज की प्रतिज्ञा सूची है । जो कुछ भी घटनाओं और वितरित राज्य के साथ मॉडलिंग की जा सकती है, उसे वैश्विक राज्य और दो तरह से बाध्यकारी किया जा सकता है, और सामान्य तौर पर आप बहुत बेहतर होंगे।
bbsimonbb

1

आपके नियंत्रण रेंडर से प्रभावित होने पर Ref और इवेंट बस दोनों में समस्याएँ हैं 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 },
})

यह 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()

इसने मेरे लिए काम किया।


इस उत्तर में स्पष्टीकरण की बहुत कमी है
vsync
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.