Programing

Vue.js 계산된 속성은 이벤트를 통과할 때 반응성을 잃는다.

c10106 2022. 4. 10. 23:07
반응형

Vue.js 계산된 속성은 이벤트를 통과할 때 반응성을 잃는다.

나는 a를 가지고 있다.Modal모달이 표시되어야 할 때마다 이벤트를 통해 콘텐츠를 전달하는 내 기본 앱의 구성 요소.모달 콘텐츠는 항상 "선택" 또는 "제거"와 같이 각 항목과 관련된 액션을 포함하는 목록이다.

Vue.component('modal', {
  data() {
    return {
      shown: false,
      items: [],
      callback: ()=>{}
    }
  },
  mounted() {
    EventBus.$on('showModal', this.show);
  },
  template: `<ul v-if="shown">
    <li v-for="item in items">
      {{ item }} <button @click="callback(item)">Remove</button>
    </li>
  </ul>`,
  methods: {
    show(items, callback) {
      this.shown = true;
      this.items = items;
      this.callback = callback;
    }
  }
});

슬프게도, 아래 구성 요소와 같이 계산된 속성을 해당 모달에 전달하면 반응적 링크가 끊어진다 -> 액션이 "제거"된 경우 목록은 업데이트되지 않는다.

Vue.component('comp', {
  data() {
    return {obj: {a: 'foo', b: 'bar'}}
  },
  computed: {
    objKeys() {
      return Object.keys(this.obj);
    }
  },
  template: `<div>
    <button @click="showModal">Show Modal</button>
    <modal></modal>
  </div>`,
  methods: {
    remove(name) {
      this.$delete(this.obj, name);
    },
    showModal() {
      EventBus.$emit('showModal', this.objKeys, this.remove);
    }
  }
});

이 바이올린에서 최소 사용 사례를 참조하십시오. https://jsfiddle.net/christophfriedrich/cm778wgj/14/

나는 이것이 벌레라고 생각한다 - Vue는 그것을 기억해야 하지 않는가?objKeys렌더링에 사용됨Modal업데이트? (변경 내용 전달)objobjKeys작업).그렇지 않다면 내가 무엇을 잘못하고 어떻게 내가 원하는 결과를 얻을 수 있을까?

당신은 모달의 복제품을 가지고 일한다.items:

 template: `<ul v-if="shown">
    <li v-for="item in items">
      {{ item }} <button @click="callback(item)">Remove</button>
    </li>
  </ul>`,
  methods: {
    show(items, callback) {
      this.shown = true;
      this.items = items;
      this.callback = callback;
    }
  }

그 복사본은 다음에 호출하면 한 번 만들어진다.show그리고 당신이 복사하고 있는 것은 단지 당신이 그것을 방출하는 시간에 계산된 값이다.showModal이벤트. 뭐라고?show수신은 계산된 것이 아니며 할당하는 것은 계산된 것이 아니다.그것은 단지 가치일 뿐이다.

만약, 당신의 코드에 있는 어느 곳에서든, 당신이 그런 과제를 했다면,

someDataItem = someComputed;

데이터 항목은 계산된 값의 기능 복사본이 아니라 할당 시점의 해당 값의 스냅샷이 될 것이다.이것이 Vue에서 값을 복사하는 것이 나쁜 습관인 이유다: 그것들은 자동으로 동기화되지 않는다.

값을 복사하는 대신 관심 값을 반환하는 함수를 전달할 수 있으며, 효과적으로 get 함수를 사용할 수 있다.통사적 명확성을 위해, 당신은 그 기능을 바탕으로 계산해 낼 수 있다.그러면 당신의 코드는

const EventBus = new Vue();

Vue.component('comp', {
  data() {
    return {
      obj: {
        a: 'foo',
        b: 'bar'
      }
    }
  },
  computed: {
    objKeys() {
      return Object.keys(this.obj);
    }
  },
  template: `<div>
    <div>Entire object: {{ obj }}</div>
    <div>Just the keys: {{ objKeys }}</div>
    <button @click="remove('a')">Remove a</button>
    <button @click="remove('b')">Remove b</button>
    <button @click="showModal">Show Modal</button>
    <modal></modal>
  </div>`,
  methods: {
    remove(name) {
      this.$delete(this.obj, name);
    },
    showModal() {
      EventBus.$emit('showModal', () => this.objKeys, this.remove);
    }
  }
});

Vue.component('modal', {
  data() {
    return {
      shown: false,
      getItems: null,
      callback: () => {}
    }
  },
  mounted() {
    EventBus.$on('showModal', this.show);
  },
  template: `<div v-if="shown">
  <ul v-if="items.length>0">
    <li v-for="item in items">
      {{ item }} <button @click="callback(item)">Remove</button>
    </li>
  </ul>
  <em v-else>empty</em>
</div>`,
  computed: {
    items() {
      return this.getItems && this.getItems();
    }
  },
  methods: {
    show(getItems, callback) {
      this.shown = true;
      this.getItems = getItems;
      this.callback = callback;
    }
  }
});

var app = new Vue({
  el: '#app'
})
<script src="//unpkg.com/vue@latest/dist/vue.js"></script>
<div id="app">
  <comp></comp>
</div>

함수에 값을 전달하고 구성 요소에 소품을 전달하지 않는 경우.소품은 반응하지만 가치는 가치관에 불과하다.포함modal…을 본떠서comp, 그래서 그것을 가져가기 위해 다시 작업한다 (적어도)items소품으로그러면 반응하게 될 것이다.

나는 콜백을 통과하기보다는 부모에게 배출-이벤트-프로세스를 따르도록 하는 것을 추천한다.

const EventBus = new Vue();

Vue.component('comp', {
  data() {
    return {
      obj: {
        a: 'foo',
        b: 'bar'
      }
    }
  },
  computed: {
    objKeys() {
      return Object.keys(this.obj);
    }
  },
  template: `<div>
    <div>Entire object: {{ obj }}</div>
    <div>Just the keys: {{ objKeys }}</div>
    <button @click="remove('a')">Remove a</button>
    <button @click="remove('b')">Remove b</button>
    <button @click="showModal">Show Modal</button>
    <modal :items="objKeys" event-name="remove" @remove="remove"></modal>
  </div>`,
  methods: {
    remove(name) {
      this.$delete(this.obj, name);
    },
    showModal() {
      EventBus.$emit('showModal');
    }
  }
});

Vue.component('modal', {
  props: ['items', 'eventName'],
  data() {
    return {
      shown: false,
    }
  },
  mounted() {
    EventBus.$on('showModal', this.show);
  },
  template: `<div v-if="shown">
  <ul v-if="items.length>0">
    <li v-for="item in items">
      {{ item }} <button @click="emitEvent(item)">Remove</button>
    </li>
  </ul>
  <em v-else>empty</em>
</div>`,
  methods: {
    show(items, callback) {
      this.shown = true;
    },
    emitEvent(item) {
      this.$emit(this.eventName, item);
    }
  }
});

var app = new Vue({
  el: '#app'
})
<script src="//unpkg.com/vue@latest/dist/vue.js"></script>
<div id="app">
  <comp></comp>
</div>

참조URL: https://stackoverflow.com/questions/49259249/vue-js-computed-property-loses-its-reactivity-when-passed-through-an-event

반응형