programing

Vue - 객체 어레이를 자세히 감시하고 변경을 계산하고 있습니까?

goodsources 2022. 7. 18. 22:20
반응형

Vue - 객체 어레이를 자세히 감시하고 변경을 계산하고 있습니까?

내 어레이는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.)

그리고 제가 만든 코드펜에서는 빈 배열이 되어버렸습니다.변경된 객체는 제가 예상한 대로가 아닙니다.

왜 이런 일이 일어나고 있는지, 어디가 잘못됐는지 알려주신다면 대단히 감사하겠습니다!

오래된 값과 새로운 값의 비교 기능에 문제가 있습니다.나중에 디버깅 작업이 늘어나기 때문에 너무 복잡해지지 않는 것이 좋습니다.당신은 그것을 단순하게 해야 합니다.

가장 좋은 방법은 다음 명령어를 작성하는 것입니다.person-component각자가 자신의 컴포넌트 안에서 개별적으로 감시하는 방법은 다음과 같습니다.

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

내부 사용자 구성 요소를 감시하기 위한 작업 예를 아래에 확인하십시오.부모측에서 취급하고 싶은 경우는,$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>

저는 당신의 문제를 해결하기 위해 구현을 변경했고, 오래된 변경 사항을 추적하여 그것과 비교하는 객체를 만들었습니다.문제를 해결하는 데 사용할 수 있습니다.

여기서는 오래된 값을 별도의 변수에 저장하고 워치에 사용하는 메서드를 만들었습니다.

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,
    }
  }
})

최신 정보를 참조해 주세요. 코드펜

그것은 잘 정의된 행동이다.변환된 개체의 이전 값을 가져올 수 없습니다.그 이유는 둘 다newVal그리고.oldVal같은 오브젝트를 참조합니다.Vue는 사용자가 변환한 개체의 이전 복사본을 보관하지 않습니다.

개체를 다른 개체로 교체했다면 Vue가 올바른 참조를 제공했을 것입니다.

를 참조해 주세요.Note를 참조해 주세요. (vm.$watch )

여기랑 여기랑 더 자세히.

컴포넌트 솔루션과 딥 클론 솔루션에는 장점이 있지만 다음과 같은 문제도 있습니다.

  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()이치이 항목에서 원하는 처리를 수행할 수 있습니다.

또, 리스트에 아이템을 추가/삭제하는 경우에 대비해, 보다 복잡한 시나리오도 여기에 기재하고 있습니다(이미 있는 아이템을 조작하는 것 만이 아닙니다).

이것은 제가 물체를 자세히 관찰할 때 사용하는 것입니다.내 요구 사항은 개체의 하위 필드를 감시하는 것이었습니다.

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

Object가 하려면 Vuej 또는 NUXTJS를 해야 .deep: true 중인

    watch: {
      'Object.key': {
         handler (val) {
             console.log(val)
         },
         deep: true
       } 
     }

     watch: {
      array: {
         handler (val) {
             console.log(val)
         },
         deep: true
       } 
     }

언급URL : https://stackoverflow.com/questions/41135188/vue-deep-watching-an-array-of-objects-and-calculating-the-change

반응형