To प्रॉप्स ’बदलाव के लिए कैसे सुनें


256

में VueJs 2.0 डॉक्स मैं किसी भी हुक कि पर सुनने हैं नहीं मिल सकता है propsबदल जाता है।

क्या VueJs में ऐसे हुक onPropsUpdated()या समान हैं?

अपडेट करें

जैसा कि @wostex ने सुझाव दिया, मैंने watchअपनी संपत्ति की कोशिश की लेकिन कुछ भी नहीं बदला। तब मुझे महसूस हुआ कि मुझे एक विशेष मामला मिला है:

<template>
    <child :my-prop="myProp"></child>
</template>

<script>
   export default {
      props: ['myProp']
   }
</script>

मैं पास myPropकर रहा हूं कि मूल घटक घटक को प्राप्त करता है child। फिर watch: {myProp: ...}काम नहीं कर रहा है।



1
मुझे यकीन नहीं है कि मैं आपके मामले को सही ढंग से समझ पा रहा हूं। क्या आप बता सकते हैं कि आपका सटीक लक्ष्य क्या है? "जब कुछ होता है, तो मैं चाहता हूं कि यहां (जहां?)" कुछ कठोरता हो। क्या आप पैरेंट प्रोप वैल्यू को मैन्युअल रूप से बदलने की कोशिश कर रहे हैं? यदि हाँ तो यह पूरी तरह से अलग मामला है।
ईगोर स्टैम्बकियो

@wostex, यहाँ कोडपेन है । बुरी बात यह है कि कलम में यह काम कर रहा है ...
Amio.io

1
मैं देखता हूं, समस्या कहीं और है। मुझे अपना कोड दिखाओ, मैं देख लूंगा।
ईगोर स्टैम्बकियो

1
हैलो। यहाँ: ChannelDetail.vue आप FacebookPageDetail घटक को कहीं भी आयात नहीं करते हैं, लेकिन इसे घोषित करते हैं: gist.github.com/zatziky/ ... मुझे लगता है कि यह FacebookChannelDetail.vue होना चाहिए। FacebookDetail.vue के रूप में FacebookPageDetail के रूप में आयात किया गया है, इसके अलावा यह ठीक दिखता है
Egor स्टंबाकियो

जवाबों:


320

आप watchरंगमंच की सामग्री पर कुछ कोड निष्पादित करने के लिए सहारा कर सकते हैं:

new Vue({
  el: '#app',
  data: {
    text: 'Hello'
  },
  components: {
    'child' : {
      template: `<p>{{ myprop }}</p>`,
      props: ['myprop'],
      watch: { 
      	myprop: function(newVal, oldVal) { // watch it
          console.log('Prop changed: ', newVal, ' | was: ', oldVal)
        }
      }
    }
  }
});
<script src="https://unpkg.com/vue/dist/vue.js"></script>

<div id="app">
  <child :myprop="text"></child>
  <button @click="text = 'Another text'">Change text</button>
</div>


1
Wostex के लिए Thx, मैंने पहले ही प्रयास कर लिया है watch। आपके उदाहरण के कारण मैंने महसूस किया कि मेरा मामला थोड़ा अलग है। मैंने अपना प्रश्न अपडेट कर दिया है।
Amio.io

1
देखो यह घटक की तरह लग रहा है।
रीसिविवप्रॉप्स

@yussan हाँ, लेकिन यह एक ही प्रोप पर लागू है जिसे आपको ट्रैक करने की आवश्यकता है।
ईगोर स्टैम्बकियो

1
मुझे पता है कि घड़ी को हतोत्साहित किया जाता है क्योंकि आमतौर पर गणना की गई संपत्ति का उपयोग करना बेहतर होता है, लेकिन क्या घड़ी का उपयोग करने के साथ कोई प्रदर्शन समस्याएं हैं?
सेथवेट

1
@SethWhite क्या मैं समझता हूँ कि कैसे पर्यवेक्षक पैटर्न का उपयोग करके Vue में प्रतिक्रियाशीलता को संभाला जाता है , पर नजर रखने वालों को गणना या अन्य प्रतिक्रियाशील डेटा की तुलना में कम कुशल नहीं है। ऐसे मामलों में जहां एक संपत्ति का मूल्य कई मूल्यों पर निर्भर करता है, एक संगणित प्रोप प्रत्येक फ़ंक्शन के लिए एक अलग वॉच कॉलबैक बनाम परिणाम चलाएगा। मुझे लगता है कि ज्यादातर सामान्य उपयोग के मामलों में, एक गणना की गई संपत्ति का वांछित परिणाम होगा।
plong0

83

क्या आपने यह कोशिश की है?

watch: {
  myProp: {
    // the callback will be called immediately after the start of the observation
    immediate: true, 
    handler (val, oldVal) {
      // do your stuff
    }
  }
}

https://vuejs.org/v2/api/#watch


7
यह मेरे लिए काम किया, जहां जवाब नहीं था - शायद यह एक अद्यतन है। धन्यवाद BearInBox :)
अनुदान

2
तत्काल: सच यह मेरे लिए तय
basbase

2
इस तरह घड़ी सेट करना मेरे लिए भी तय है, धन्यवाद!
adamk22

2
मेरे लिए भी काम करता है। यह स्वीकृत उत्तर होना चाहिए
टाइटो 10

1
मेरे लिए भी काम किया जबकि स्वीकृत उत्तर नहीं दिया। +1
रॉबर्टो

25

वह,

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

  watch: {
    $props: {
      handler() {
        this.parseData();
      },
      deep: true,
      immediate: true,
    },

इस उदाहरण से दूर ले जाने के लिए महत्वपूर्ण बिंदु deep: trueयह है कि यह न केवल $ प्रॉप्स को देखता है, बल्कि यह जैसे नेस्टेड मान भी हैprops.myProp

आप इस विस्तारित घड़ी विकल्पों के बारे में अधिक जानकारी यहां देख सकते हैं: https://vuejs.org/v2/api/#vm-watch


खुशी है कि यह आगे भुगतान करने के लिए! सौभाग्य!
जोशचर

7

आपको यह समझने की आवश्यकता है, आपके द्वारा किए जा रहे घटक पदानुक्रम और आप कैसे प्रॉपर से गुजर रहे हैं, निश्चित रूप से आपका मामला विशेष है और आमतौर पर देवों द्वारा सामना नहीं किया गया है।

मूल घटक -myProp-> बाल घटक -myProp-> पोते का घटक

यदि myProp को मूल घटक में बदल दिया जाता है तो यह बाल घटक में भी परिलक्षित होगा

और अगर myProp को बाल घटक में बदल दिया जाता है, तो यह पोते के घटक में भी परिलक्षित होगा

इसलिए यदि myProp को मूल घटक में बदला जाता है तो यह पोते के घटक में परिलक्षित होगा । (अब तक तो सब ठीक है)।

इसलिए पदानुक्रम के नीचे आपको कुछ भी करने की आवश्यकता नहीं होती है, स्वाभाविक रूप से प्रतिक्रियाशील होगा।

अब पदानुक्रम में ऊपर जाने की बात कर रहे हैं

अगर myProp को ग्रैंडचिल्ड घटक में बदल दिया जाता है तो यह चाइल्ड घटक में परिलक्षित नहीं होगा । आपको बच्चे में .sync संशोधक का उपयोग करना होगा और ग्रैंडचिल्ड घटक से ईवेंट का उत्सर्जन करना होगा।

अगर myProp को चाइल्ड कंपोनेंट में बदल दिया जाए तो यह पैरेंट कंपोनेंट में परिलक्षित नहीं होगा । आपको माता-पिता में .sync संशोधक का उपयोग करना होगा और बच्चे के घटक से घटना का उत्सर्जन करना होगा।

अगर myProp को ग्रैंडहिल्ड घटक में बदल दिया जाता है तो यह मूल घटक (स्पष्ट रूप से) में परिलक्षित नहीं होगा । आपको .sync मॉडिफ़ायर चाइल्ड का उपयोग करना होगा और पोते के घटक से ईमट इवेंट, फिर चाइल्ड कंपोनेंट में प्रॉप देखें और बदलाव पर एक ईवेंट उत्सर्जित करें, जो कि .sync मॉडिफ़ायर का उपयोग करके सुने जा रहे हैं।

आइए भ्रम से बचने के लिए कुछ कोड देखें

Parent.vue

<template>
    <div>
    <child :myProp.sync="myProp"></child>
    <input v-model="myProp"/>
    <p>{{myProp}}</p>
</div>
</template>

<script>

    import child from './Child.vue'

    export default{
        data(){
            return{
                myProp:"hello"
            }
        },
        components:{
            child
        }
    }
</script>

<style scoped>
</style>

Child.vue

<template>
<div>   <grand-child :myProp.sync="myProp"></grand-child>
    <p>{{myProp}}</p>
</div>

</template>

<script>
    import grandChild from './Grandchild.vue'

    export default{
        components:{
            grandChild
        },
        props:['myProp'],
        watch:{
            'myProp'(){
                this.$emit('update:myProp',this.myProp)

            }
        }
    }
</script>

<style>

</style>

Grandchild.vue

<template>
    <div><p>{{myProp}}</p>
    <input v-model="myProp" @input="changed"/>
    </div>
</template>

<script>
    export default{
        props:['myProp'],
        methods:{
            changed(event){
                this.$emit('update:myProp',this.myProp)
            }
        }
    }
</script>

<style>

</style>

लेकिन इसके बाद आप वाउ कहने की चिल्लाहट को नोटिस करने में मदद नहीं करेंगे

जब भी मूल घटक पुन: रेंडर किया जाता है, तो मान को सीधे एक प्रोप को बदलने से बचें।

जैसा कि मैंने पहले उल्लेख किया है कि अधिकांश देवता इस मुद्दे का सामना नहीं करते हैं, क्योंकि यह एक विरोधी पैटर्न है। इसलिए आपको यह चेतावनी मिलती है।

लेकिन अपने मुद्दे को हल करने के लिए (आपके डिजाइन के अनुसार)। मेरा मानना ​​है कि आपको उपरोक्त कार्य (ईमानदार होने के लिए हैक) करना होगा। मैं अभी भी सलाह देता हूं कि आपको अपने डिजाइन पर पुनर्विचार करना चाहिए और बग्स के लिए कम संभावना है।

मुझे उम्मीद है यह मदद करेगा।


6

यकीन नहीं होता कि आपने इसे हल कर लिया है (और अगर मैं सही तरीके से समझता हूं), लेकिन यहाँ मेरा विचार है:

यदि माता-पिता को MyProp प्राप्त होता है, और आप चाहते हैं कि वह बच्चे के पास जाए और उसे बच्चे में देखे, तो माता-पिता के पास myProp (संदर्भ नहीं) की प्रति होनी चाहिए।

इसे इस्तेमाल करे:

new Vue({
  el: '#app',
  data: {
    text: 'Hello'
  },
  components: {
    'parent': {
      props: ['myProp'],
      computed: {
        myInnerProp() { return myProp.clone(); } //eg. myProp.slice() for array
      }
    },
    'child': {
      props: ['myProp'],
      watch: {
        myProp(val, oldval) { now val will differ from oldval }
      }
    }
  }
}

और HTML में:

<child :my-prop="myInnerProp"></child>

वास्तव में आपको ऐसी परिस्थितियों में जटिल संग्रह पर काम करते समय बहुत सावधान रहना होगा (कुछ समय गुजरना)


अच्छा विचार। मैं फिलहाल इसे मान्य नहीं कर सकता। जब मैं फिर से काम करूंगा, तब मैं इसकी जांच करूंगा।
Amio.io

1
धन्यवाद @ m.cichacz, ने एक ही गलती की और बच्चे को एक कॉपी पास करने के लिए आपके सुझाव के लिए तुरंत धन्यवाद दिया
undefinederror

4

दो तरह से बंधन के लिए आपको .sync संशोधक का उपयोग करना होगा

<child :myprop.sync="text"></child>

अधिक जानकारी...

और आपको किसी भी बदलाव को सुनने और अपडेट करने के लिए चाइल्ड कंपोनेंट में वॉच प्रॉपर्टी का उपयोग करना होगा

props: ['myprop'],
  watch: { 
    myprop: function(newVal, oldVal) { // watch it
      console.log('Prop changed: ', newVal, ' | was: ', oldVal)
    }
  }

सच है, यह बाल घटकों में परिवर्तन के लिए देखने का नया तरीका है।
Amio.io

2

मैं एक संगणित संपत्ति के साथ काम करता हूं:

    items:{
        get(){
            return this.resources;
        },
        set(v){
            this.$emit("update:resources", v)
        }
    },

संसाधन इस मामले में एक संपत्ति है:

props: [ 'resources' ]

1

मेरे लिए यह एक विशिष्ट समाधान है जो एक विशिष्ट प्रोप (परिवर्तन) प्राप्त करता है और इसके साथ तर्क बनाता है

मैं परिवर्तन प्राप्त करने के बाद तर्क बनाने के लिए गुणों का उपयोग propsऔर चर करूँगाcomputed

export default {
name: 'getObjectDetail',
filters: {},
components: {},
props: {
  objectDetail: { // <--- we could access to this value with this.objectDetail
    type: Object,
    required: true
  }
},
computed: {
  _objectDetail: {
    let value = false
    // ...
    // if || do || while -- whatever logic
    // insert validation logic with this.objectDetail (prop value)
    value = true
    // ...
    return value 
  }
}

इसलिए, हम html रेंडर पर _objectDetail का उपयोग कर सकते हैं

<span>
  {{ _objectDetail }}
</span>

या किसी विधि में:

literallySomeMethod: function() {
   if (this._objectDetail) {
   ....
   }
}

0

परिवर्तनों का पता लगाने के लिए आप घड़ी मोड का उपयोग कर सकते हैं:

सब कुछ परमाणु स्तर पर करें। इसलिए पहले जांच लें कि घड़ी विधि खुद कह रही है या नहीं कि अंदर कुछ सांत्वना देकर। एक बार यह स्थापित हो जाने के बाद कि घड़ी को कॉल किया जा रहा है, अपने व्यावसायिक तर्क के साथ इसे तोड़ दें।

watch: { 
  myProp: function() {
   console.log('Prop changed')
  }
}

0

यदि मुझे परिवर्तन प्राप्त करने के बाद तर्क बनाने की आवश्यकता है, तो मैं गुणों का उपयोग propsऔर चर करता computedहूं

export default {
name: 'getObjectDetail',
filters: {},
components: {},
props: {
    objectDetail: {
      type: Object,
      required: true
    }
},
computed: {
    _objectDetail: {
        let value = false
        ...

        if (someValidation)
        ...
    }
}

-1

यदि myProp एक ऑब्जेक्ट है, तो इसे सामान्य रूप से नहीं बदला जा सकता है। इसलिए, घड़ी को कभी ट्रिगर नहीं किया जाएगा। MyProp को नहीं बदला जाने का कारण यह है कि आपने ज्यादातर मामलों में MyProp की कुछ कुंजियाँ निर्धारित की हैं। myProp अभी भी एक है। "MyProp.a" जैसे myProp के प्रॉपर देखने की कोशिश करें, इसे काम करना चाहिए।



-1

@JoeSchr का अच्छा जवाब है। यदि आप 'गहरा: सच्चा' नहीं चाहते हैं, तो ऐसा करने का एक और तरीका है।

 mounted() {
    this.yourMethod();
    // re-render any time a prop changes
    Object.keys(this.$options.props).forEach(key => {
      this.$watch(key, this.yourMethod);
    });
  },
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.