جافاسكريبت - كيفية الاستماع لتغييرات 'props'


في وثائق VueJs 2.0 لا أستطيع العثور على أي خطاطيف تستمع لتغييرات props.

هل لدى VueJs مثل هذه الخطافات مثل onPropsUpdated() أو ما شابه؟

تحديث

كما اقترح @wostex، حاولت مراقبة خاصيتي ولكن لم يتغير شيء. ثم أدركت أن لدي حالة خاصة:

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

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

أنا أقوم بتمرير myProp الذي يستقبله المكون الأب إلى المكون child. ثم watch: {myProp: ...} لا يعمل.

الإجابة رقم 1

يمكنك مراقبة الخصائص لتنفيذ بعض الشيفرات عند تغيّر الخصائص:

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@2/dist/vue.min.js"></script>

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

الإجابة رقم 2

هل جربت هذا؟

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

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

الإجابة رقم 3

في حالتي، كنت بحاجة إلى حل حيث أنه كلما تغيرت أي خصائص، كنت بحاجة إلى إعادة تحليل بياناتي. كنت متعبًا من إنشاء مراقب منفصل لكل خصائص، لذلك استخدمت هذا:

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

النقطة الأساسية التي يجب أخذها من هذا المثال هي استخدام deep: true بحيث لا يراقب فقط $props بل أيضًا القيم المتداخلة فيه مثل على سبيل المثال props.myProp

يمكنك معرفة المزيد حول خيارات المراقبة الموسعة هذه هنا: https://v2.vuejs.org/v2/api/#vm-watch

الإجابة رقم 4

تحتاج إلى أن تفهم، التسلسل الهرمي للمكونات الذي لديك وكيف تقوم بتمرير الخصائص، بالتأكيد حالتك خاصة وليست عادة ما يواجهها المطورون.

المكون الأب -myProp-> المكون الابن -myProp-> المكون الحفيد

إذا تم تغيير myProp في المكون الأب، فسيتم انعكاسه أيضًا في المكون الابن.

وإذا تم تغيير myProp في المكون الابن، فسيتم انعكاسه أيضًا في المكون الحفيد.

لذا إذا تم تغيير myProp في المكون الأب، فإنه سينعكس في المكون الحفيد. (حتى الآن كل شيء جيد).

لذلك في المستويات الأدنى من التسلسل الهرمي، لا تحتاج إلى فعل أي شيء، فالمُلزِمات ستكون تفاعلية بطبيعتها.

الآن نتحدث عن الصعود في التسلسل الهرمي

إذا تم تغيير myProp في مكون grandChild، فلن يتم عكسه في مكون child. عليك استخدام معدّل .sync في child وإطلاق حدث من مكون grandChild.

إذا تم تغيير myProp في المكون الفرعي، فلن ينعكس ذلك في المكون الأصل. عليك استخدام معدل .sync في المكون الأصل وإصدار حدث من المكون الفرعي.

إذا تم تغيير myProp في مكون grandChild، فلن يتم عكسه في المكون الأب (من الواضح). عليك استخدام المعدل .sync في الطفل وإصدار حدث من مكون grandchild، ثم مراقبة الخاصية في مكون الطفل وإصدار حدث عند التغيير يتم الاستماع إليه من قبل المكون الأب باستخدام المعدل .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>

لكن بعد هذا لن تساعد على ملاحظة التحذيرات الصارخة في Vue التي تقول

تجنب تعديل الخاصية مباشرةً لأن القيمة ستُستبدل كلما أعاد المكوّن الأب العرض.

مرة أخرى كما ذكرت سابقًا، معظم المطورين لا يواجهون هذه المشكلة، لأنها نمط غير صحيح. لهذا السبب تحصل على هذا التحذير.

ولكن من أجل حل مشكلتك (وفقًا لتصميمك). أعتقد أنه يجب عليك القيام بالحل البديل أعلاه (لكي أكون صريحًا، هو اختراق). ومع ذلك، أنصحك بإعادة التفكير في تصميمك وجعله أقل عرضة للأخطاء.

آمل أن يكون مفيدًا.

الإجابة رقم 5

لربط البيانات ثنائي الاتجاه، عليك استخدام المعدّل .sync:

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

المزيد من التفاصيل...

ويجب عليك استخدام خاصية المراقبة في المكوّن الفرعي للاستماع وتحديث أي تغييرات

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