【问题标题】:Why does my two separate Vue components override each others data?为什么我的两个单独的 Vue 组件会覆盖彼此的数据?
【发布时间】:2021-01-14 20:51:27
【问题描述】:

用例

给定以下 vue 组件:

<template>
  <div>
    <slot>{{ title }}</slot>
    <ul>
      <li v-for="label in labels" :key="label">
        <input
          type="checkbox"
          v-model="checked"
          :label="label"
          :id="label"
          :value="label"
        />
        <label :for="label">{{ label }}</label>
      </li>
    </ul>
  </div>
</template>

<script>
import Component from "vue-class-component";
import Vue from "vue";

@Component({
  props: {
    labels: {
      type: Array,
    },
    title: {
      type: String,
    },
  },
  watch: {
    checked: [
      {
        handler: "updateParent",
      },
    ],
  },
})
export default class CheckboxList extends Vue {
  checked = [];

  updateParent() {
    this.$emit("update", this.checked);
  }
}
</script>

组件将呈现它从父级接收到的labels 属性的复选框列表。

当在同一页面中使用两个组件时,使用v-if 切换如下:

<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png" width="10%" />
    <hr />
    <button type="button" @click="state = 'numbers'">
      Show number checklist
    </button>
    <button type="button" @click="state = 'letters'">
      Show letter checklist
    </button>

    <CheckboxList
      v-if="state === 'numbers'"
      title="numbers"
      :labels="numbers"
      @update="checkedNumbers = $event"
    ></CheckboxList>
    <CheckboxList
      v-if="state === 'letters'"
      title="letters"
      :labels="letters"
      @update="checkedLetters = $event"
    ></CheckboxList>

    <div>
      <span>Checked letters:</span> {{ checkedLetters }}
      <span>Checked numbers:</span> {{ checkedNumbers }}
    </div>
  </div>
</template>

<script>
import Vue from "vue";
import HelloWorld from "./components/HelloWorld";
import CheckboxList from "./CheckboxList.vue";
import Component from "vue-class-component";

@Component({
  components: {
    CheckboxList,
  },
})
export default class App extends Vue {
  numbers = [1, 2, 3, 4, 5];
  letters = ["a", "b", "c", "d"];
  state = "numbers";

  checkedLetters = [];
  checkedNumbers = [];
}
</script>

这将创建以下 UI:

为什么在两个组件之间切换(使用v-if)并选中复选框时 - 数据会混淆导致以下行为?

可以在此处找到完整的工作示例:https://codesandbox.io/s/epic-resonance-plwvi?file=/src/App.vue

【问题讨论】:

    标签: javascript vue.js vuejs2 vue-component


    【解决方案1】:

    作为 Vues 内部优化的一部分,它将努力在其指令中重用组件(例如 v-ifv-for)作为默认行为。

    这在他们的docs 中有记录。

    不幸的是,这确实是 Vue 的默认设置,请考虑添加一个具有唯一值的 key 属性,以“强制”Vue 将它们视为单独的组件:

     <CheckboxList
      key="numbers" <!-- Add this to distinct between the two -->
      v-if="state === 'numbers'"
      title="numbers"
      :labels="numbers"
      @update="checkedNumbers = $event"
      ></CheckboxList>
      <CheckboxList
       key="letters" <!-- Add this to distinct between the two -->
       v-if="state === 'letters'"
       title="letters"
       :labels="letters"
       @update="checkedLetters = $event"
       ></CheckboxList>
    

    请注意,当组件一次性渲染时不需要这样做 - 没有条件切换或循环:

    <!-- 
         Since both are rendered at the same time, 
         they will be considered separate components 
         and won't require a 'key' prop to distinguish between the two 
    -->
     <CheckboxList
      title="numbers"
      :labels="numbers"
      @update="checkedNumbers = $event"
      ></CheckboxList>
      <CheckboxList
       title="letters"
       :labels="letters"
       @update="checkedLetters = $event"
       ></CheckboxList>
    

    【讨论】:

      猜你喜欢
      • 2015-11-02
      • 1970-01-01
      • 2021-07-18
      • 2022-06-10
      • 2012-10-15
      • 1970-01-01
      • 1970-01-01
      • 2019-10-12
      • 1970-01-01
      相关资源
      最近更新 更多