ভ্যূ - ডিপ অবজেক্টের অ্যারে দেখছে এবং পরিবর্তনের গণনা করছে?


108

আমার নামে একটি অ্যারে peopleরয়েছে যা এতে নিখরচায় অবজেক্টস রয়েছে:

আগে

[
  {id: 0, name: 'Bob', age: 27},
  {id: 1, name: 'Frank', age: 32},
  {id: 2, name: 'Joe', age: 38}
]

এটি পরিবর্তন করতে পারে:

পরে

[
  {id: 0, name: 'Bob', age: 27},
  {id: 1, name: 'Frank', age: 33},
  {id: 2, name: 'Joe', age: 38}
]

লক্ষ্য করুন ফ্রাঙ্ক সবেমাত্র 33 বছর বয়সী।

আমার একটি অ্যাপ রয়েছে যেখানে আমি লোকদের অ্যারে দেখার চেষ্টা করছি এবং যখন কোনও মান পরিবর্তন হয় তখন পরিবর্তনটি লগইন করুন:

<style>
input {
  display: block;
}
</style>

<div id="app">
  <input type="text" v-for="(person, index) in people" v-model="people[index].age" />
</div>

<script>
new Vue({
  el: '#app',
  data: {
    people: [
      {id: 0, name: 'Bob', age: 27},
      {id: 1, name: 'Frank', age: 32},
      {id: 2, name: 'Joe', age: 38}
    ]
  },
  watch: {
    people: {
      handler: function (val, oldVal) {
        // Return the object that changed
        var changed = val.filter( function( p, idx ) {
          return Object.keys(p).some( function( prop ) {
            return p[prop] !== oldVal[idx][prop];
          })
        })
        // Log it
        console.log(changed)
      },
      deep: true
    }
  }
})
</script>

আমি গতকাল অ্যারে তুলনা সম্পর্কে জিজ্ঞাসা করেছি এমন প্রশ্নের উপর ভিত্তি করেছিলাম এবং দ্রুত কাজের উত্তর নির্বাচন করেছি।

সুতরাং, এই মুহুর্তে আমি এর ফলাফল দেখতে প্রত্যাশা করব: { id: 1, name: 'Frank', age: 33 }

তবে কনসোলটিতে আমি যা পেয়েছি তা হ'ল (মনে রাখবেন যে এটি একটি উপাদানটিতে রেখেছিলাম):

[Vue warn]: Error in watcher "people" 
(found in anonymous component - use the "name" option for better debugging messages.)

এবং আমি তৈরি কোডপেনে , ফলাফলটি একটি খালি অ্যারে এবং পরিবর্তিত অবজেক্ট নয় যা পরিবর্তিত হয়েছিল যা আমি প্রত্যাশা করেছিলাম।

কেউ যদি পরামর্শ দিতে পারে যে কেন এটি হচ্ছে বা আমি এখানে ভুল হয়ে গেলাম তবে এটির প্রশংসা হবে, অনেক ধন্যবাদ!

উত্তর:


136

পুরানো মান এবং নতুন মানের মধ্যে আপনার তুলনা ফাংশনটিতে কিছু সমস্যা রয়েছে। জিনিসগুলিকে এত বেশি জটিল না করা ভাল, কারণ এটি পরে আপনার ডিবাগিং প্রচেষ্টা বাড়িয়ে তুলবে। আপনার এটি সহজ রাখা উচিত।

সর্বোত্তম উপায় হ'ল একটি তৈরি করা person-componentএবং প্রত্যেক ব্যক্তিকে পৃথক পৃথক পৃথক পৃথক উপাদানগুলির মধ্যে দেখতে, যা নীচে দেখানো হয়েছে:

<person-component :person="person" v-for="person in people"></person-component>

ব্যক্তি উপাদানগুলির ভিতরে দেখার জন্য দয়া করে নীচে একটি কার্যকারী উদাহরণ পান example আপনি যদি এটি প্যারেন্টের পক্ষ থেকে পরিচালনা করতে চান তবে আপনি পরিবর্তিত ব্যক্তির $emitসমন্বিত কোনও ইভেন্ট উপরের দিকে প্রেরণ করতে ব্যবহার করতে পারেন id

Vue.component('person-component', {
    props: ["person"],
    template: `
        <div class="person">
            {{person.name}}
            <input type='text' v-model='person.age'/>
        </div>`,
    watch: {
        person: {
            handler: function(newValue) {
                console.log("Person with ID:" + newValue.id + " modified")
                console.log("New age: " + newValue.age)
            },
            deep: true
        }
    }
});

new Vue({
    el: '#app',
    data: {
        people: [
          {id: 0, name: 'Bob', age: 27},
          {id: 1, name: 'Frank', age: 32},
          {id: 2, name: 'Joe', age: 38}
        ]
    }
});
<script src="https://unpkg.com/vue@2.1.5/dist/vue.js"></script>
<body>
    <div id="app">
        <p>List of people:</p>
        <person-component :person="person" v-for="person in people"></person-component>
    </div>
</body>


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

2
যাইহোক, এটি ব্যাখ্যা করার জন্য সময় দেওয়ার জন্য ধন্যবাদ, এটি ভ্যু সম্পর্কে যা আরও প্রশংসা করি সে সম্পর্কে আরও জানতে আমাকে সহায়তা করেছে!
ক্রেগ ভ্যান টন্ডার

এটি উপলব্ধি করতে আমার কিছুটা সময় লেগেছিল তবে আপনি একেবারেই সঠিক, এটি একটি কবজির মতো কাজ করে এবং যদি আপনি বিভ্রান্তি এবং অন্যান্য সমস্যাগুলি এড়াতে চান তবে জিনিসগুলি করার সঠিক উপায় :)
ক্রেগ ভ্যান টন্ডার

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

1
শেষ পর্যন্ত যদিও, আপনার উপায়টি এক নজরে বোঝা সহজ এবং মান পরিবর্তিত হলে কী উপলব্ধ তা বিবেচনা করে আরও নমনীয়তা সরবরাহ করে। এটিকে ভ্যুতে সহজ রাখার সুবিধাগুলি বুঝতে আমাকে অনেক সাহায্য করেছে তবে আপনি আমার অন্যান্য প্রশ্নে যেমন দেখেছেন তেমন কিছুতেই আটকে গেলেন। অনেক ধন্যবাদ! :)
ক্রেগ ভ্যান টন্ডার

21

আপনার সমস্যার সমাধান পেতে আমি এটির বাস্তবায়ন পরিবর্তন করেছি, আমি পুরানো পরিবর্তনগুলি ট্র্যাক করতে এবং এটির সাথে তুলনা করার জন্য একটি বিষয় তৈরি করেছি made আপনি আপনার সমস্যা সমাধানের জন্য এটি ব্যবহার করতে পারেন।

এখানে আমি একটি পদ্ধতি তৈরি করেছি, যার মধ্যে পুরানো মানটি একটি পৃথক ভেরিয়েবলে সংরক্ষণ করা হবে এবং এটি একটি ঘড়িতে ব্যবহৃত হবে।

new Vue({
  methods: {
    setValue: function() {
      this.$data.oldPeople = _.cloneDeep(this.$data.people);
    },
  },
  mounted() {
    this.setValue();
  },
  el: '#app',
  data: {
    people: [
      {id: 0, name: 'Bob', age: 27},
      {id: 1, name: 'Frank', age: 32},
      {id: 2, name: 'Joe', age: 38}
    ],
    oldPeople: []
  },
  watch: {
    people: {
      handler: function (after, before) {
        // Return the object that changed
        var vm = this;
        let changed = after.filter( function( p, idx ) {
          return Object.keys(p).some( function( prop ) {
            return p[prop] !== vm.$data.oldPeople[idx][prop];
          })
        })
        // Log it
        vm.setValue();
        console.log(changed)
      },
      deep: true,
    }
  }
})

আপডেট করা কোডেপেন দেখুন


সুতরাং যখন এটি মাউন্ট করা হয় তখন ডেটার একটি অনুলিপি সঞ্চয় করে এবং এর সাথে তুলনা করতে এটি ব্যবহার করুন। আকর্ষণীয়, তবে আমার ব্যবহারের বিষয়টি আরও জটিল হবে এবং অ্যারে থেকে অবজেক্টগুলি যুক্ত করার সময় এবং সরানোর সময় এটি কীভাবে কার্যকর হবে সে সম্পর্কে আমি নিশ্চিত নই, @ কিরক সমস্যাটি সমাধানের জন্য ভাল লিঙ্ক সরবরাহ করেছিল। তবে আমি জানতাম না যে আপনি ব্যবহার করতে পারেন vm.$data, আপনাকে ধন্যবাদ!
ক্রেগ ভ্যান টন্ডার

হ্যাঁ, এবং আমি আবার পদ্ধতিটি কল করে ঘড়ির পরে আপডেট করছি, এটির মাধ্যমে যদি আপনি মূল মানটিতে ফিরে যান, তবে এটি পরিবর্তনটিও ট্র্যাক করবে।
ভিপলক

ওহ, আমি লক্ষ্য করিনি যে সেখানে লুকিয়ে থাকা, অনেক তাৎপর্যপূর্ণ এবং এটি মোকাবেলার জন্য একটি জটিল জটিল উপায় (গিথুবের সমাধানের বিপরীতে)।
ক্রেগ ভ্যান টন্ডার

এবং হ্যাঁ, আপনি যদি মূল অ্যারে থেকে কিছু যুক্ত বা সরিয়ে দিচ্ছেন, কেবল আবার পদ্ধতিটিকে কল করুন এবং আপনি আবার সমাধানের সাথে যেতে ভাল are
ভিপলক

1
_ক্লোনডিপ () সত্যিই আমার ক্ষেত্রে সহায়তা করেছে। ধন্যবাদ!! সত্যিই সহায়ক!
ক্রিশ্চিয়ানা পেরেইরা

18

এটি ভালভাবে সংজ্ঞায়িত আচরণ। কোনও রূপান্তরিত বস্তুর জন্য আপনি পুরানো মানটি পেতে পারেন না । উভয় কারণ newValএবং oldValএকই বস্তুর উল্লেখ করুন। আপনি যে পরিবর্তন করেছেন তা ভ্যুও কোনও পুরানো অনুলিপি রাখবে না

আপনি যদি অন্য কোনওটির সাথে অবজেক্টটি প্রতিস্থাপন করেন তবে ভ্যু আপনাকে সঠিক তথ্য সরবরাহ করতে পারত।

ডক্সেNote বিভাগটি পড়ুন । ( vm.$watch)

এটি এখানে এবং এখানে আরও


3
ওহে আমার টুপি, অনেক অনেক ধন্যবাদ! এটি একটি ছদ্মবেশী ... আমি পুরোপুরি ভাল এবং ওল্ডভালটি আলাদা হওয়ার প্রত্যাশা করছিলাম তবে তাদের পরীক্ষা করে দেখার পরে আমি দেখতে পাচ্ছি এটি নতুন অ্যারের দুটি কপি, এটি এর আগে ট্র্যাক করে না। আরও কিছুটা পড়ুন এবং একই ভুল বোঝাবুঝি সম্পর্কে এই উত্তরহীন এসও প্রশ্নের সন্ধান পেয়েছেন: স্ট্যাকওভারফ্লো /
ক্রেগ ভ্যান টন্ডার

5

এটি কোনও বস্তুর গভীর পর্যবেক্ষণ করতে আমি ব্যবহার করি। আমার প্রয়োজনটি অবজেক্টের শিশু ক্ষেত্রগুলি দেখছিল।

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

আমি বিশ্বাস করি যে আপনি সম্ভবত যে ক্যাএটটির স্ট্যাকওভারফ্লো.com/a/41136186/2110294-তে বর্ণনা করেছেন তা বোঝা যাচ্ছে না । কেবল স্পষ্ট করে বলতে গেলে, এটি প্রশ্নের সমাধান নয় এবং নির্দিষ্ট পরিস্থিতিতে আপনি যেমনটি আশা করেছিলেন তেমন কার্যকর হবে না।
ক্রেগ ভ্যান টন্ডার

এই ঠিক আমি খুঁজছিলাম !. ধন্যবাদ
জয়দীপ শিল

এখানেও একই, আমার যা দরকার ছিল ঠিক তাই !! ধন্যবাদ।
গুন্টার

4

উপাদান সমাধান এবং ডিপ-ক্লোন সমাধানগুলির সুবিধাগুলি রয়েছে তবে এতে সমস্যা রয়েছে:

  1. কখনও কখনও আপনি বিমূর্ত ডেটাতে পরিবর্তনগুলি ট্র্যাক করতে চান - এই ডেটার চারপাশে উপাদানগুলি তৈরি করা বরাবরই বোধগম্য হয় না।

  2. প্রতিবার আপনি পরিবর্তন করার সময় আপনার পুরো ডেটা কাঠামোকে গভীরভাবে ক্লোনিং করা খুব ব্যয়বহুল হতে পারে ।

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

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

এই কাঠামোর সাহায্যে, handleChange()পরিবর্তিত নির্দিষ্ট তালিকা আইটেমটি পাবেন - সেখান থেকে আপনি আপনার পছন্দসই কোনও পরিচালনা করতে পারেন can

আমি এখানে আরও জটিল দৃশ্যের নথিভুক্ত করেছি , আপনি যদি আপনার তালিকায় আইটেমগুলি যুক্ত / সরিয়ে দিচ্ছেন (কেবলমাত্র ইতিমধ্যে সেখানে থাকা আইটেমগুলিতে হস্তক্ষেপ না করে)।


ধন্যবাদ এরিক, আপনি বৈধ পয়েন্ট উপস্থাপন করেন এবং প্রদত্ত পদ্ধতিটি যদি প্রশ্নের সমাধান হিসাবে প্রয়োগ করা হয় তবে সুনির্দিষ্টভাবে কার্যকর।
ক্রেগ ভ্যান টন্ডার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.