Vue.js - নেস্টেড ডেটা কীভাবে সঠিকভাবে পর্যবেক্ষণ করবেন


413

কিছু প্রোপ বৈচিত্রের জন্য কীভাবে সঠিকভাবে পর্যবেক্ষণ করা যায় তা বোঝার চেষ্টা করছি। আমার একটি প্যারেন্ট উপাদান (.ভ্যু ফাইল) রয়েছে যা একটি এজ্যাক্স কল থেকে ডেটা গ্রহণ করে, কোনও বস্তুর ভিতরে ডেটা রাখে এবং এটি আমার প্রয়োগের সরলকরণের নীচে ভি-ফর ডাইরেক্টিভের মাধ্যমে কিছু শিশু উপাদান রেন্ডার করতে ব্যবহার করে:

<template>
    <div>
        <player v-for="(item, key, index) in players"
            :item="item"
            :index="index"
            :key="key"">
        </player>
    </div>
</template>

... তারপরে <script>ট্যাগের ভিতরে :

 data(){
     return {
         players: {}
 },
 created(){
        let self = this;
        this.$http.get('../serv/config/player.php').then((response) => {
            let pls = response.body;
            for (let p in pls) {
                self.$set(self.players, p, pls[p]);
            }
    });
}

আইটেম অবজেক্টস এর মত:

item:{
   prop: value,
   someOtherProp: {
       nestedProp: nestedValue,
       myArray: [{type: "a", num: 1},{type: "b" num: 6} ...]
    },
}

এখন, আমার সন্তানের "প্লেয়ার" উপাদানটির ভিতরে আমি কোনও আইটেমের সম্পত্তি পরিবর্তনের জন্য দেখার চেষ্টা করছি এবং আমি ব্যবহার করি:

...
watch:{
    'item.someOtherProp'(newVal){
        //to work with changes in "myArray"
    },
    'item.prop'(newVal){
        //to work with changes in prop
    }
}

এটি কাজ করে তবে এটি আমার কাছে কিছুটা জটিল বলে মনে হচ্ছে এবং আমি ভাবছিলাম যে এটি করার সঠিক উপায় এটি। আমার লক্ষ্য হ'ল প্রতিবার কিছু ক্রিয়া সম্পাদন করা propবা myArrayনতুন উপাদানগুলি পাওয়া বা বিদ্যমানগুলির মধ্যে কিছু প্রকারের পরিবর্তন। কোন পরামর্শ প্রশংসা করা হবে।


9
"item.someOtherProp": function (newVal, oldVal){@ রন প্রস্তাবিত হিসাবে ঠিক ব্যবহার করুন ।
Reiner

1
@ রেইনার এই প্রশ্নটিতে তিনি এড়াতে চেয়েছিলেন ঠিক সেটাই ছিল; এটি ES5 সিনট্যাক্স ব্যবহার করে ঠিক একই জিনিস। গণনা দেখার ক্ষেত্রে আসলে কোনও অতিরিক্ত ওভারহেড নেই এবং এটি বিভিন্ন পরিস্থিতিতে একটি কার্যকর কৌশল।
ক্রেগ_h

1
keysকোনও অবজেক্টের সমস্ত অভ্যন্তরের পরিবর্তনের জন্য নজর রাখা কি সম্ভব ? উদাহরণ:"item.*": function(val){...}
চার্লি

উত্তর:


622

আপনি এটির জন্য গভীর পর্যবেক্ষক ব্যবহার করতে পারেন :

watch: {
  item: {
     handler(val){
       // do stuff
     },
     deep: true
  }
}

এটি এখন itemঅ্যারেতে থাকা বস্তুগুলির যে কোনও পরিবর্তন এবং অ্যারে নিজেই সংযোজন ( ভ্যু.সেটের সাথে ব্যবহৃত হলে ) সনাক্ত করবে। এখানে একটি জেএসফিডাল: http://jsfiddle.net/je2rw3rs/

সম্পাদনা

আপনি যদি শীর্ষ স্তরের অবজেক্টের প্রতিটি পরিবর্তনের জন্য দেখতে না চান এবং সরাসরি নেস্টেড অবজেক্টগুলি দেখার জন্য কিছুটা বিশ্রী সিনট্যাক্স চান তবে আপনি computedতার পরিবর্তে কেবল এটি দেখতে পারেন :

var vm = new Vue({
  el: '#app',
  computed: {
    foo() {
      return this.item.foo;
    }
  },
  watch: {
    foo() {
      console.log('Foo Changed!');
    }
  },
  data: {
    item: {
      foo: 'foo'
    }
  }
})

এখানে জেএসফিডাল: http://jsfiddle.net/oa07r5fw/


2
এই পদ্ধতিতে "হ্যান্ডলার" ডেকে আনা হবে যখনই কোনও প্রপ এর ভিন্নতা আছে, আমার উদ্দেশ্য হ্যান্ডলারগুলিকে পৃথক করে "প্রোপ" হয় বা মাইআর্রে "কিছুটা অন্যরূপে" আলাদাভাবে রয়েছে কিনা তা পর্যবেক্ষণ করার জন্য
প্লাস্টিক

9
আপনি যদি কেবল নির্দিষ্ট নেস্টেড অবজেক্টের পরিবর্তন দেখতে চান তবে আপনি যা করছেন তা ঠিক আছে। আপনি যদি আরও কম বিশ্রী বাক্য গঠন চান তবে আপনি তার computedপরিবর্তে দেখতে পারেন : jsfiddle.net/c52nda7x
craig_h

ঠিক আমি যা খুঁজছিলাম, এখন এটি আমার পক্ষে এতটা যুক্তিযুক্ত বলে মনে হচ্ছে: একটি গণিত সম্পত্তি তৈরি করুন যা নেস্টেড প্রোপটি ফিরিয়ে দেয় এবং এটির জন্য নজর রাখে। Tnx অনেক।
প্লাস্টিক

আমি কেবল যুক্ত করতে চাই - দ্বিতীয় বিকল্পটি আসল প্রহরী থেকে সত্যিই খুব বেশি আলাদা নয়। অভ্যন্তরীণভাবে একটি গণনা করা সম্পত্তি হ'ল ফাংশনটির সমস্ত রেফারেন্সড অবজেক্ট / মানগুলির উপর নজরদারি যা ফাংশনের ফলাফলের জন্য ডেটা-মান নির্ধারণ করে। - সুতরাং আপনি সম্ভবত একই প্রভাবটি দিয়ে কোডটিকে কিছুটা আরও সংশ্লেষিত করেন।
ফ্যালকো

22
@ ফ্যালকো আমি এখানে একটি মন্তব্যে উত্তরটি সন্ধান করেছি । পিয়ারবোল্ট ইঙ্গিত করেছেন যে এটি একক উদ্ধৃতিতে ঘড়ির নাম রেখে কাজটি করা যেতে পারে। আমি এটি পরীক্ষা করেছি এবং এটি কাজ করে। সুতরাং watch: { 'item.foo' : function(newVal, oldVal) { // do work here }} এক্ষেত্রে এটি প্রিটি স্মার্ট হবে। আমি ভ্যূ ভালবাসি!
রন সি

436

আরেকটি ভাল পদ্ধতির এবং কিছুটা মার্জিত এটি নীচে রয়েছে:

 watch:{
     'item.someOtherProp': function (newVal, oldVal){
         //to work with changes in someOtherProp
     },
     'item.prop': function(newVal, oldVal){
         //to work with changes in prop
     }
 }

(এই মন্তব্যটি আমি এখানে মন্তব্যটিতে @ পেরেবোল্টের কাছ থেকে শিখেছি )


47
উপায় আরও মার্জিত (কিছুটা নয়): পি। এটি Vue.js ডকুমেন্টেশনে হওয়া উচিত কারণ এটি সাধারণ ব্যবহারের ক্ষেত্রে। আমি একটি সমাধানের জন্য কয়েক ঘন্টা অনুসন্ধান করেছিলাম, আপনার উত্তরের জন্য ধন্যবাদ।
ক্লদিউ

11
@ সাইম্বা এটি আকর্ষণীয় যে লোকেরা খেয়াল করেন নি যে ওপি কেবল ES5সিনট্যাক্সে এড়াতে বলেছিল । আমরা অবশ্যই যুক্তি দিতে পারি যে ES2015 method definitionনিজেই খুব মার্জিত নয়, তবে এটি একধরণের প্রশ্নের বিন্দুটিকে মিস করে, যা নাম মোড়ানো এড়াতে কীভাবে উদ্ধৃতি হয়। আমি অনুমান করছি যে বেশিরভাগ লোক আসল প্রশ্নটি নিয়ে চকচকে করছে, যার উত্তর ইতিমধ্যে রয়েছে এবং আপনি আসলে এমন কিছু সন্ধান করছেন যা আপনার বক্তব্য হিসাবে খুব ভাল নথিভুক্ত নয়,
ক্রেগ_

1
@ ক্রেইগ_এইচ আকর্ষণীয় পয়েন্ট। নেস্টেড প্রপ দেখার জন্য ভাল উপায় খুঁজতে আমি মূলত ঘন্টার পর ঘন্টা শিকার করছিলাম। এবং এই প্রশ্নের শিরোনামটি আমার কাছে পাওয়া সবচেয়ে কাছের প্রশ্ন ছিল তবে আমি মিস করেছি যে তিনি প্রশ্নের শরীরে একটি উদ্ধৃত প্রপ লিস্ট করেছেন তবে উত্তরগুলি এত মার্জিত নয় found অবশেষে আমি অন্য প্রশ্নের মন্তব্যে উদ্ধৃত প্রপ পদ্ধতির সন্ধান পেয়েছি এবং এসও সম্পর্কিত উদ্ধৃতিপ্রাপ্ত পদ্ধতির ডকুমেন্টেশন হিসাবে এটির নিজের উত্তর দেওয়ার জন্য একটি প্রশ্ন তৈরি করতে প্ররোচিত হয়েছিল। তবে এই প্রশ্নটি হ'ল আমার শিরোনামটি কী হত তাই আমি উত্তরটি এখানে যুক্ত করেছিলাম। হয়তো আমার একটি নতুন প্রশ্ন তৈরি করা উচিত ছিল।
রন সি

9
@ রনসি এটি একটি জনপ্রিয় প্রশ্ন এবং আপনার উত্তরটি হ'ল অনেক লোক সন্ধান করছে, তাই আমার মনে হয় এটি এখানে ভাল বসে। আমাদের সকলের হাতেই সীমিত সময় রয়েছে এবং আমরা বেশিরভাগই সবেমাত্র প্রশ্নগুলি পড়েছি, সুতরাং এটি আপনার দেওয়া উত্তরের সমালোচনা ছিল না, আমার মূল উত্তরটি সুনির্দিষ্ট ছিল উল্লেখ করে আমি কিছুটা পেডেন্টিক হচ্ছি প্রশ্ন এবং মতামত করা উদ্দেশ্য ছিল না। আমি আসলে "দেখার গণনা" পদ্ধতির পছন্দ করি, তবে অনেকে কম সংশ্লেষিত "কোট" পদ্ধতির পছন্দ করেন, যা আপনি উত্তর দিয়ে সংক্ষেপে সংক্ষিপ্তসার করেছেন।
ক্রেগ_২

10
সরকারী ডকুমেন্টেশন এখন এই পদ্ধতির অন্তর্ভুক্ত
feihcsim

19

শিশু অবজেক্টগুলিতে ভয়েজে গভীর নজর রাখে

new Vue({
    el: "#myElement",
    data: {
        entity: {
            properties: []
        }
    },
    watch: {
        'entity.properties': {
            handler: function (after, before) {
                // Changes detected. Do work...     
            },
            deep: true
        }
    }
});

8

আপনি যদি কিছু সময়ের জন্য কোনও সম্পত্তি দেখতে চান এবং তারপরে এটি অন-ওয়াচিং করতে চান তবে কীভাবে?

বা একটি লাইব্রেরির শিশু উপাদান সম্পত্তি দেখতে?

আপনি "গতিশীল প্রহরী" ব্যবহার করতে পারেন:

this.$watch(
 'object.property', //what you want to watch
 (newVal, oldVal) => {
    //execute your code here
 }
)

$watchএকটি unwatch ফাংশন যা যদি এটা বলা হয় পর্যবেক্ষক বন্ধ করবে ফেরৎ।

var unwatch = vm.$watch('a', cb)
// later, teardown the watcher
unwatch()

এছাড়াও আপনি deepবিকল্পটি ব্যবহার করতে পারেন :

this.$watch(
'someObject', () => {
    //execute your code here
},
{ deep: true }
)

দস্তাবেজগুলিতে একবার দেখে নিচ্ছেন তা নিশ্চিত করুন


2
দস্তাবেজ অনুসারে , আপনি Note that you should not use an arrow function to define a watcher (e.g. searchQuery: newValue => this.updateAutocomplete(newValue)). The reason is arrow functions bind the parent context, so this will not be the Vue instance as you expect and this.updateAutocomplete will be undefined.
কোনও প্রহরীকে

7

এখানে উল্লিখিত না দেখে, vue-property-decoratorআপনি যদি আপনার Vueক্লাসটি প্রসারিত করেন তবে প্যাটার্নটি ব্যবহার করাও সম্ভব ।

import { Watch, Vue } from 'vue-property-decorator';

export default class SomeClass extends Vue {
   ...

   @Watch('item.someOtherProp')
   someOtherPropChange(newVal, oldVal) {
      // do something
   }

   ...
}

5

আমি এই সমাধানটি 'হ্যাক' করার জন্য যুক্ত করার আরেকটি উপায় হ'ল: আমি একটি পৃথক computedমান সেট করেছিলাম যা কেবল নেস্টেড অবজেক্টের মান ফিরিয়ে দেয়।

data : function(){
    return {
        my_object : {
            my_deep_object : {
                my_value : "hello world";
            }.
        },
    };
},
computed : {
    helper_name : function(){
        return this.my_object.my_deep_object.my_value;
    },
},
watch : {
    helper_name : function(newVal, oldVal){
        // do this...
    }
}

ভাল একটি;) তবে অ্যারেগুলির সাথে কী? :)
ওয়েবকেন্দ্র

3

ব্যবহারের স্বীকৃত উত্তরের সাথে আমার সমস্যাটি deep: trueহ'ল যখন কোনও অ্যারের গভীর পর্যবেক্ষণ করা হয় তখন আমি সহজেই চিহ্নিত করতে পারি না যে অ্যারের কোন উপাদানটিতে পরিবর্তন রয়েছে। আমি খুঁজে পেয়েছি শুধুমাত্র পরিষ্কার সমাধান হ'ল এই উত্তর, যা কোনও উপাদান কীভাবে তৈরি করবেন তা ব্যাখ্যা করে যাতে আপনি প্রতিটি অ্যারে উপাদান পৃথকভাবে দেখতে পারেন।


1
হ্যাঁ এটি সত্য, তবে গভীর পর্যবেক্ষকের পক্ষে এটি নয় (বাস্তবে আপনি খুঁজে পাবেন oldValএবং newValউভয়ই একই বস্তুর রেফারেন্স দেবেন, একই রকম)। একটি উদ্দেশ্য deep watcherহয় কিছু করতে নির্গত যেমন একটি ঘটনা, যখন মান পরিবর্তন করেন, যেমন, মেক মনি এর উত্তরে সরু আউট হিসাবে একটি Ajax কল ইত্যাদি অন্যথা, আপনি সম্ভবত চান একটি অংশ।
ক্রেগ_ ঘন্টা

আমার ব্যক্তিগত পরিবর্তনগুলি ট্র্যাক করার একই সমস্যা ছিল! যদিও আমি একটি সমাধান খুঁজে পেয়েছি এবং এটি এখানে নথিভুক্ত করেছি ।
এরিক কোওপম্যানস

3

একটি তালিকায় পৃথক পরিবর্তিত আইটেম ট্র্যাকিং

আপনি যদি তালিকার সমস্ত আইটেম দেখতে চান এবং তালিকার কোন আইটেমটি পরিবর্তিত হয়েছে তা জানতে চান, আপনি প্রতিটি আইটেমে আলাদা আলাদাভাবে কাস্টম নজরদার সেটআপ করতে পারেন, এর মতো:

var vm = new Vue({
  data: {
    list: [
      {name: 'obj1 to watch'},
      {name: 'obj2 to watch'},
    ],
  },
  methods: {
    handleChange (newVal, oldVal) {
      // Handle changes here!
      // NOTE: For mutated objects, newVal and oldVal will be identical.
      console.log(newVal);
    },
  },
  created () {
    this.list.forEach((val) => {
      this.$watch(() => val, this.handleChange, {deep: true});
    });
  },
});

যদি আপনার তালিকা অবিলম্বে জনবসতিপূর্ণ না হয় (মূল প্রশ্নের মতো) তবে আপনি যুক্তিটি createdযেখানে প্রয়োজন সেখানে সরিয়ে নিতে পারেন , উদাহরণস্বরূপ.then() ব্লকের ।

একটি পরিবর্তনশীল তালিকা দেখুন

যদি আপনার তালিকাটি নিজেই নতুন বা সরানো আইটেমগুলি আপডেট করতে আপডেট করে, আমি একটি কার্যকর প্যাটার্ন তৈরি করেছি যা "অগভীর" তালিকাটি নিজেই দেখেন এবং তালিকা পরিবর্তন হিসাবে গতিশীলভাবে আইটেমগুলি দেখেন / দেখেন না:

// NOTE: This example uses Lodash (_.differenceBy and _.pull) to compare lists
//       and remove list items. The same result could be achieved with lots of
//       list.indexOf(...) if you need to avoid external libraries.

var vm = new Vue({
  data: {
    list: [
      {name: 'obj1 to watch'},
      {name: 'obj2 to watch'},
    ],
    watchTracker: [],
  },
  methods: {
    handleChange (newVal, oldVal) {
      // Handle changes here!
      console.log(newVal);
    },
    updateWatchers () {
      // Helper function for comparing list items to the "watchTracker".
      const getItem = (val) => val.item || val;

      // Items that aren't already watched: watch and add to watched list.
      _.differenceBy(this.list, this.watchTracker, getItem).forEach((item) => {
        const unwatch = this.$watch(() => item, this.handleChange, {deep: true});
        this.watchTracker.push({ item: item, unwatch: unwatch });
        // Uncomment below if adding a new item to the list should count as a "change".
        // this.handleChange(item);
      });

      // Items that no longer exist: unwatch and remove from the watched list.
      _.differenceBy(this.watchTracker, this.list, getItem).forEach((watchObj) => {
        watchObj.unwatch();
        _.pull(this.watchTracker, watchObj);
        // Optionally add any further cleanup in here for when items are removed.
      });
    },
  },
  watch: {
    list () {
      return this.updateWatchers();
    },
  },
  created () {
    return this.updateWatchers();
  },
});

0

আমার পক্ষে উত্তরটির কোনওটিই কাজ করছিল না। আসলে আপনি যদি একাধিকবার কল করার জন্য উপাদানগুলির সাথে নেস্টেড ডেটা দেখতে চান। সুতরাং তাদের সনাক্ত করার জন্য তাদেরকে বিভিন্ন প্রপস সহ ডাকা হয়। উদাহরণ স্বরূপ<MyComponent chart="chart1"/> <MyComponent chart="chart2"/> আমার কার্যতালিকা হ'ল একটি অ্যাডিয়োনাল ভিউক্স স্টেট ভেরিয়েবল তৈরি করা, যা আমি নিজেই সর্বশেষ আপডেট হওয়া সম্পত্তিটির দিকে ইঙ্গিত করতে আপডেট করি।

এখানে একটি ভেক্সেক্স.টি বাস্তবায়নের উদাহরণ রয়েছে:

export default new Vuex.Store({
    state: {
        hovEpacTduList: {},  // a json of arrays to be shared by different components, 
                             // for example  hovEpacTduList["chart1"]=[2,6,9]
        hovEpacTduListChangeForChart: "chart1"  // to watch for latest update, 
                                                // here to access "chart1" update 
   },
   mutations: {
        setHovEpacTduList: (state, payload) => {
            state.hovEpacTduListChangeForChart = payload.chart // we will watch hovEpacTduListChangeForChart
            state.hovEpacTduList[payload.chart] = payload.list // instead of hovEpacTduList, which vuex cannot watch
        },
}

স্টোর আপডেট করার জন্য যে কোনও উপাদান ফাংশনে:

    const payload = {chart:"chart1", list: [4,6,3]}
    this.$store.commit('setHovEpacTduList', payload);

আপডেট পেতে এখন যে কোনও উপাদান:

    computed: {
        hovEpacTduListChangeForChart() {
            return this.$store.state.hovEpacTduListChangeForChart;
        }
    },
    watch: {
        hovEpacTduListChangeForChart(chart) {
            if (chart === this.chart)  // the component was created with chart as a prop <MyComponent chart="chart1"/> 
                console.log("Update! for", chart, this.$store.state.hovEpacTduList[chart]);
        },
    },
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.