माता-पिता की घटनाओं पर बाल घटक पर फ़ंक्शन कैसे कॉल करें


164

प्रसंग

Vue 2.0 में प्रलेखन और अन्य स्पष्ट रूप से इंगित करते हैं कि माता-पिता से बच्चे तक संचार प्रॉप्स के माध्यम से होता है।

सवाल

एक अभिभावक अपने बच्चे को यह कैसे बताता है कि प्रॉप्स के माध्यम से एक घटना हुई है?

क्या मुझे केवल एक प्रोप नामक घटना देखनी चाहिए? यह सही नहीं लगता है, न ही विकल्प ( $emit/ $onबच्चे के माता-पिता के लिए है, और एक हब मॉडल दूर के तत्वों के लिए है)।

उदाहरण

मेरे पास एक अभिभावक कंटेनर है और उसे अपने बाल कंटेनर को यह बताना होगा कि एपीआई पर कुछ क्रियाओं को करना ठीक है। मुझे कार्यों को ट्रिगर करने में सक्षम होने की आवश्यकता है।

जवाबों:


234

बच्चे को एक घटक दें refऔर $refsसीधे बाल घटक पर एक विधि को कॉल करने के लिए उपयोग करें।

एचटीएमएल:

<div id="app">
  <child-component ref="childComponent"></child-component>
  <button @click="click">Click</button>  
</div>

जावास्क्रिप्ट:

var ChildComponent = {
  template: '<div>{{value}}</div>',
  data: function () {
    return {
      value: 0
    };
  },
  methods: {
    setValue: function(value) {
        this.value = value;
    }
  }
}

new Vue({
  el: '#app',
  components: {
    'child-component': ChildComponent
  },
  methods: {
    click: function() {
        this.$refs.childComponent.setValue(2.0);
    }
  }
})

अधिक जानकारी के लिए, Refs पर Vue प्रलेखन देखें ।


13
इस तरह माता-पिता और बच्चे के घटक युग्मित हो जाते हैं। वास्तविक घटनाओं के लिए, जब आप किसी कार्रवाई को ट्रिगर करने के लिए सिर्फ एक प्रस्ताव को नहीं बदल सकते, तो मैं @Roy J द्वारा सुझाए गए बस समाधान के साथ जाऊंगा
Jared

3
डॉक्स के लिए एक रेफरी एक सहायक aswell vuejs.org/v2/guide/… होगा
ctf0

मेरे बाल घटक में, विशेष कारणों से, मुझे प्रतिक्रियाशीलता को समाप्त करने के लिए वी-एक बार उपयोग करना पड़ा। इस प्रकार माता-पिता से बच्चे के लिए प्रॉप पास करना एक विकल्प नहीं था, इसलिए इस समाधान ने चाल चली!
जॉन

1
नौसिखिया सवाल: एक प्रोप बनाने केref बजाय इसका उपयोग क्यों किया जाता है , जो इसके मूल्य को देखता है और फिर इसे माता-पिता के किसी अन्य कार्य के लिए उत्सर्जित करता है? मेरा मतलब है कि यह करने के लिए बहुत कुछ है, लेकिन refसुरक्षित भी उपयोग कर रहा है ? धन्यवाद
Irfandy Jip

5
@ इर्फंडीजिप- हां, refसुरक्षित है। आम तौर पर, यह हतोत्साहित किया जाता है क्योंकि Vue समुदाय बच्चों को राज्य देने के लिए पसंद करता है, और माता-पिता को वापस करता है। सामान्यतया, यह अधिक पृथक, आंतरिक रूप से सुसंगत घटकों (एक अच्छी बात ™) की ओर जाता है। लेकिन, यदि आप बच्चे को जो जानकारी दे रहे हैं, वह वास्तव में एक घटना (या एक कमांड) है, तो राज्य को संशोधित करना सही पैटर्न नहीं है। उस स्थिति में, एक विधि का उपयोग करके कॉल refकरना पूरी तरह से ठीक है, और यह दुर्घटना या कुछ भी करने वाला नहीं है।
9

76

आप जो वर्णन कर रहे हैं, वह माता-पिता में स्थिति का परिवर्तन है। आप एक प्रस्ताव के माध्यम से बच्चे को देते हैं। जैसा आपने सुझाव दिया था, आप watchवैसा ही होगा । जब बच्चा कार्रवाई करता है, तो यह माता-पिता को एक के माध्यम से सूचित करता है emit, और माता-पिता फिर से राज्य को बदल सकते हैं।

यदि आप सही मायने में एक बच्चे को घटनाओं को पारित करना चाहते हैं, तो आप बस (जो कि सिर्फ एक मात्र उदाहरण है) बनाकर और उसे एक प्रस्ताव के रूप में बच्चे को पारित कर सकते हैं


2
मुझे लगता है कि यह केवल आधिकारिक V.JS शैली गाइड और सर्वोत्तम प्रथाओं के अनुरूप है। यदि आप v-modelघटक पर शॉर्टहैंड का उपयोग करते हैं, तो आप कम कोड वाले संबंधित ईवेंट का उत्सर्जन करके भी आसानी से मूल्य रीसेट कर सकते हैं।
फाल्को

उदाहरण के लिए, जब कोई उपयोगकर्ता किसी बटन पर क्लिक करता है तो मैं एक चेतावनी देना चाहता हूं। क्या आप उदाहरण के लिए प्रस्ताव करते हैं: - एक झंडा देखें - इस ध्वज को 0 से 1 तक सेट करें जब एक क्लिक होता है, - कुछ करें - ध्वज को रीसेट करें
Sinan Erdem

9
यह बहुत असुविधाजनक है, आपको propएक बच्चे में एक अतिरिक्त बनाना होगा , एक अतिरिक्त संपत्ति में data, फिर जोड़ना watchहोगा ... यह सहज होगा यदि किसी तरह माता-पिता से बच्चे को घटनाओं को स्थानांतरित करने के लिए अंतर्निहित समर्थन था। यह स्थिति काफी बार होती है।
Илья Иеленько

1
जैसा कि @ ИльяЗеленько के अनुसार, यह अक्सर होता है, यह अभी के बारे में एक देवता होगा।
क्रेग

1
धन्यवाद @RoyJ, मुझे लगता है कि बच्चे को इसकी सदस्यता देने के लिए बस प्रोप की आवश्यकता होती है, हालांकि, मुझे लगता है कि बच्चों को नीचे भेजने की घटनाओं के पूरे विचार को वीयू में हतोत्साहित किया जाता है।
बेन वाइंडिंग

35

आप उपयोग कर सकते हैं $emitऔर $on। @RoyJ कोड का उपयोग करना:

एचटीएमएल:

<div id="app">
  <my-component></my-component>
  <button @click="click">Click</button>  
</div>

जावास्क्रिप्ट:

var Child = {
  template: '<div>{{value}}</div>',
  data: function () {
    return {
      value: 0
    };
  },
  methods: {
    setValue: function(value) {
        this.value = value;
    }
  },
  created: function() {
    this.$parent.$on('update', this.setValue);
  }
}

new Vue({
  el: '#app',
  components: {
    'my-component': Child
  },
  methods: {
    click: function() {
        this.$emit('update', 7);
    }
  }
})

चल उदाहरण: https://jsfiddle.net/rjurado/m2spy60r/1/


6
मुझे आश्चर्य है कि यह काम करता है। मैंने सोचा था कि एक बच्चे के लिए उत्सर्जन एक पैटर्न-विरोधी था, या यह इरादा केवल बच्चे से माता-पिता तक ही होना चाहिए। क्या दूसरे रास्ते पर जाने से कोई संभावित समस्याएं हैं?
मर्यादा

2
यह सबसे अच्छा तरीका नहीं माना जा सकता है, मुझे नहीं पता, लेकिन यदि आप जानते हैं कि आप क्या कर रहे हैं तो मुझे लगता है कि समस्या नहीं है। दूसरा तरीका केंद्रीय बस का उपयोग करना है: vuejs.org/v2/guide/…
drinor

14
यह बच्चे और माता-पिता के बीच एक युग्मन बनाता है और इसे बुरा अभ्यास माना जाता है
morrislaptop

5
यह केवल इसलिए काम करता है क्योंकि माता-पिता एक घटक नहीं है, लेकिन वास्तव में एक वीयू ऐप है। वास्तव में यह बस के रूप में प्रतिज्ञा उदाहरण का उपयोग कर रहा है।
जूलियो रॉड्रिग्ज

2
@ इस पर कॉल करें। $ माता-पिता इस घटक को माता-पिता पर निर्भर बनाते हैं। $ emit का उपयोग करता है और प्रॉप्स करता है ताकि Vue की संचार प्रणाली के माध्यम से एकमात्र निर्भरता हो। यह दृष्टिकोण समान घटक को घटक पदानुक्रम में कहीं भी उपयोग करने की अनुमति देता है।
morrislaptop

6

यदि आपके पास समय है, तो वेरिएबल्स (उर्फ स्टेट) देखने के लिए Vuex स्टोर का उपयोग करें या सीधे एक कार्रवाई को ट्रिगर (उर्फ प्रेषण) करें।


2
vuejs / vuex की प्रतिक्रियाशीलता के कारण, जो कि सबसे अच्छा aproach है, माता-पिता में एक क्रिया / उत्परिवर्तन बनाते हैं जो एक vuex गुण मान को बदल देते हैं और बच्चे में एक संगणित मूल्य होता है जो इसी vuex $ store.state.property.value या "watch" को प्राप्त करता है। "विधि जो कुछ करती है जब vuex" $ store.state.property.value "परिवर्तन
FabianSilva

6

बच्चे के दौरान बाइंडिंग का उपयोग करते हुए घटना-बस दृष्टिकोण को पसंद नहीं किया । क्यों? बाद में कॉल (मैं उपयोग कर रहा हूं ) संदेश हैंडलर को एक से अधिक बार बाँधता हूं - प्रति संदेश कई प्रतिक्रियाओं के लिए अग्रणी।$oncreatecreatevue-router

माता-पिता से बच्चे को सहारा देने और बच्चे में एक संपत्ति पर नजर रखने वाले ऑर्थोडॉक्स समाधान ने थोड़ा बेहतर काम किया । केवल समस्या यह है कि बच्चा केवल मूल्य परिवर्तन पर कार्य कर सकता है। एक ही संदेश को कई बार पास करने से एक संक्रमण को मजबूर करने के लिए किसी प्रकार की बहीखाता पद्धति की आवश्यकता होती है ताकि बच्चा परिवर्तन उठा सके।

मैंने पाया है कि अगर मैं संदेश को एक सरणी में लपेटता हूं, तो यह हमेशा बच्चे के द्रष्टा को ट्रिगर करेगा - भले ही मूल्य समान रहे।

जनक:

{
   data: function() {
      msgChild: null,
   },
   methods: {
      mMessageDoIt: function() {
         this.msgChild = ['doIt'];
      }
   }   
   ...
}

बाल:

{
   props: ['msgChild'],
   watch: {
      'msgChild': function(arMsg) {
         console.log(arMsg[0]);
      }
   }
}

HTML:

<parent>
   <child v-bind="{ 'msgChild': msgChild }"></child>
</parent>

1
मुझे लगता है कि अगर MsChild के माता-पिता पर हमेशा एक ही स्थिति है तो यह काम नहीं करेगा। उदाहरण के लिए: मैं एक घटक चाहता हूं जो एक मोडल खोलता है। यदि वर्तमान स्थिति खुली या बंद है, तो अभिभावक को कोई परवाह नहीं है, यह किसी भी क्षण मोडल को खोलना चाहता है। तो, अगर माता-पिता ऐसा करते हैं ।msgChild = true; मोडल बंद है, और फिर माता-पिता ऐसा करते हैं ।msgChild = true, बच्चे को घटना प्राप्त नहीं होगी
जॉर्ज सैंज

1
@ जोर्जसैनज: यही कारण है कि मैं डेटा आइटम को असाइन करने से पहले एक सरणी में मान लपेट रहा हूं। किसी सरणी में मान को लपेटे बिना, यह वैसा ही व्यवहार करता है जैसा आप निर्दिष्ट करते हैं। तो, MsChild = true, msgChild = true - कोई ईवेंट नहीं है। msgChild = [true], msgChild = [true] - ईवेंट!
जेसन स्टीवर्ट

1
मैंने इसे नहीं देखा। स्पष्टीकरण के लिए धन्यवाद
जॉर्ज सैंज

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

6

बाल घटकों पर विधियों को कॉल करने का एक सरल डिकॉउड तरीका है, बच्चे से एक हैंडलर का उत्सर्जन करना और फिर उसे माता-पिता से प्राप्त करना।

var Child = {
  template: '<div>{{value}}</div>',
  data: function () {
    return {
      value: 0
    };
  },
  methods: {
  	setValue(value) {
    	this.value = value;
    }
  },
  created() {
    this.$emit('handler', this.setValue);
  }
}

new Vue({
  el: '#app',
  components: {
    'my-component': Child
  },
  methods: {
  	setValueHandler(fn) {
    	this.setter = fn
    },
    click() {
    	this.setter(70)
    }
  }
})
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>

<div id="app">
  <my-component @handler="setValueHandler"></my-component>
  <button @click="click">Click</button>  
</div>

अभिभावक बच्चे के हैंडलर फंक्शन पर नज़र रखता है और जब भी आवश्यकता होती है कॉल करता है।


मुझे पसंद है जहां यह समाधान हो रहा है लेकिन माता-पिता में वास्तव में "this.setter" क्या है?
क्रेग

यह हैंडलर घटना के तर्क के रूप में चाइल्ड घटक द्वारा उत्सर्जित सेटवैल्यू फंक्शन संदर्भ है।
नीलोबारप

2

नीचे का उदाहरण आत्म व्याख्यात्मक है। जहां से रीफ्स और इवेंट्स का इस्तेमाल फंक्शन और पैरेंट और बच्चे को कॉल करने के लिए किया जा सकता है।

// PARENT
<template>
  <parent>
    <child
      @onChange="childCallBack"
      ref="childRef"
      :data="moduleData"
    />
    <button @click="callChild">Call Method in child</button>
  </parent>
</template>

<script>
export default {
  methods: {
    callChild() {
      this.$refs.childRef.childMethod('Hi from parent');
    },
    childCallBack(message) {
      console.log('message from child', message);
    }
  }
};
</script>

// CHILD
<template>
  <child>
    <button @click="callParent">Call Parent</button>
  </child>
</template>

<script>
export default {
  methods: {
    callParent() {
      this.$emit('onChange', 'hi from child');
    },
    childMethod(message) {
      console.log('message from parent', message);
    }
  }
}
</script>

1

मुझे लगता है कि हमें बच्चे के तरीकों का उपयोग करने के लिए माता-पिता की आवश्यकता के बारे में विचार करना चाहिए। वास्तव में, माता-पिता को बच्चे के तरीके की चिंता करने की ज़रूरत नहीं है, लेकिन बच्चे के घटक को एफएसए (परिमित राज्य मशीन) के रूप में इलाज कर सकते हैं। घटक घटक। बाल घटक की स्थिति को नियंत्रित करने के लिए। स्थिति में बदलाव देखने के लिए या केवल गणना फ़ंक्शन का उपयोग करने के लिए समाधान पर्याप्त है


2
यदि आप कह रहे हैं "माता-पिता को बच्चों को नियंत्रित करने के साथ खुद को कभी चिंता नहीं करनी चाहिए", तो ऐसे मामले हैं जहां यह आवश्यक है। एक उलटी गिनती घड़ी घटक पर विचार करें। माता-पिता टाइमर को शुरू करने के लिए रीसेट करना चाह सकते हैं। बस प्रॉप्स का उपयोग करना पर्याप्त नहीं है क्योंकि समय से = 60 से समय = 60 तक प्रोप को संशोधित नहीं किया जाएगा। टाइमर को एक 'रीसेट' फ़ंक्शन को उजागर करना चाहिए जिसे माता-पिता उपयुक्त कह सकते हैं।
tbm

0

आप कुंजी का उपयोग करके बच्चे के घटक को फिर से लोड करने के लिए कुंजी का उपयोग कर सकते हैं

<component :is="child1" :filter="filter" :key="componentKey"></component>

यदि आप घटक को नए फ़िल्टर के साथ पुनः लोड करना चाहते हैं, यदि बटन क्लिक करें बाल घटक फ़िल्टर करें

reloadData() {            
   this.filter = ['filter1','filter2']
   this.componentKey += 1;  
},

और फ़ंक्शन को ट्रिगर करने के लिए फ़िल्टर का उपयोग करें

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