【问题标题】:Modifying variable in method does not update child component在方法中修改变量不会更新子组件
【发布时间】:2022-10-04 16:39:50
【问题描述】:

我正在为 Vue 如何更新道具/子组件而苦苦挣扎。

假设以下组件:

<template>
  <v-card>
    <Modification v-model="newObject"></Modification>
    <OtherComponent @close="resetObject"></OtherComponent>
  </v-card>
</template>

<script>
import { MyClass } from "classes";
import Modification from "b";
import OtherComponent from "a";

export default {
  name: "ShiftForm",
  components: { OtherComponent, Modification },
  props: {
    existingObject: {
      type: [MyClass, typeof undefined],
      required: false,
      default: undefined
    }
  },
  data() {
    return {
      newObject: undefined
    };
  },
  created() {
    this.newObject =
      this.existingObject !== undefined
        ? this.existingObject.clone()
        : new MyClass();
  },
  methods: {
    resetObject() {
      this.newObject =
        this.existingObject !== undefined
          ? this.existingObject.clone()
          : new MyClass();
    }
  }
};
</script>

MyClass 是如何定义的:

export class MyClass {
  constructor({ a= null, b=null} = {}) {
    this.a = a;
    this.b = b;
  }
  toPayload(){
    return { a:this.a , b:this.b };
  }
  clone() {
    return new MyClass(this.toPayload());
  }
}

该组件接收MyClass 的现有类实例,将其克隆(clone => new MyClass(...))并将其传递给Modification 组件,该组件根据用户输入进行一些修改。到目前为止一切顺利,修改有效。然而,一旦customEvent 被触发并且resetObject 方法被调用,newObject 被重置,但Modification 组件不会被现在重置的newObject 更新 - 它仍然显示旧的、修改后的值。我还在Modification 组件内部检查了更新是否发生:它没有。

为什么会这样?我错过了一步吗?我不知道 Vue 特定的机制吗?

注意:我发现了这个blog,它提供了强制Modification组件更新的解决方案。现在,对我来说,成为“THE”解决方案似乎很奇怪。

提前致谢。

编辑: 添加包含 console.log(JSON.stringify(this.newObject)) 的计算属性会在每次更新 newObject 时触发。 还会在模板更新中添加&lt;span&gt; {{ newObject.a }} &lt;/span&gt;

这两个测试都让我相信这个变量不仅应该是反应性的,而且实际上是反应性的。

编辑2:

Modification 组件目前由 2 个输入组件组成。 它看起来像这样。

<template>
  <v-card-text>
    <ModifyA v-model="object.a" @input="handleInput" />
    <ModifyB v-model="object.b" @input="handleInput" />
  </v-card-text>
</template>
<script>
import { MyClass } from "classes";
import ModifyA from "...";
import ModifyB from "...";
export default {
  name: "ShiftFormFields",
  components: { ModifyA, ModifyB },
  props: {
    value: {
      type: MyClass,
      required: true
    }
  },
  data() {
    return { object: this.value };
  },
  methods: {
    handleInput() {
      this.$emit("input", this.object);
    }
  }
};
</script>

如果我尝试将 ModifyA 输入添加到组件中,而不是像这样的 Modification 组件

<template>
  <v-card>
    <ModifyA v-model="newObject.a"></Modification>
    <OtherComponent @close="resetObject"></OtherComponent>
  </v-card>
</template>

resetObject 还会重置 ModifyA 组件中显示的值。

【问题讨论】:

    标签: javascript vue.js vue-reactivity


    【解决方案1】:

    您没有展示 MyClass 如何克隆您的对象。

    我猜里面的东西没有反应。

    您可以通过console.log() 进行检查,并查看控制台上显示的内容。

    如果它是反应式的,它应该显示类似MyClass {__ob__: Observer}

    您可能可以使用this.$set('propName', value) 来解决您的问题

    文档:https://v2.vuejs.org/v2/api/#vm-set

    将属性添加到响应式对象,确保新属性也是响应式的,因此会触发视图更新。这必须用于向反应性对象添加新属性,因为 Vue 无法检测到正常的属性添加(例如 this.myObject.newProperty = 'hi')。

    【讨论】:

    • 确实console.log(newObject) 显示Object { __ob__ : Object } 但所有字段都被getter 和setter 取代,所以我认为它是反应性的。另请查看我在帖子编辑中添加的两个“测试”。
    • 此外,使用this.$set(this, "newObject", ...) 不起作用。 Modification 组件中显示的值仍然是“旧编辑”的值。
    【解决方案2】:

    您的帖子中存在拼写错误,或者您的代码中也存在拼写错误并且是您问题的根源。

    在您的帖子中,您将“newObjekt”绑定到修改组件,但您的父组件具有属性“newObject”

    这是您问题的根源吗?

    【讨论】:

    • 抱歉,这只是我帖子中的一个错字。检查并编辑了我的帖子。
    【解决方案3】:

    我在this 答案中找到了解决方案。

    当我使用 Modification 组件的定义编辑我的原始帖子时

    <template>
      <v-card-text>
        <ModifyA v-model="object.a" @input="handleInput" />
        <ModifyB v-model="object.b" @input="handleInput" />
      </v-card-text>
    </template>
    <script>
    import ModifyA from "...";
    import ModifyB from "...";
    export default {
      name: "ShiftFormFields",
      components: { ModifyA, ModifyB },
      props: {
        value: {
          type: MyClass,
          required: true
        }
      },
      data() {
        return { object: this.value };
      },
      methods: {
        handleInput() {
          this.$emit("input", this.object);
        }
      }
    };
    </script>
    

    如果父组件中的value 更新,则显示字段ModifyAModifyB 不更新的“问题”。

    从上面的定义中可以看出,变量object 仅在组件初始化后才设置为value。因此object 不代表value 进行反应。

    要解决这个问题,可以使用上述答案的方法:

    <template>
      <v-card-text>
        <ModifyA v-model="object.a" />
        <ModifyB v-model="object.b" />
      </v-card-text>
    </template>
    <script>
    import { Shift } from "classes";
    import ModifyA from "...";
    import ModifyB from "...";
    export default {
      name: "ShiftFormFields",
      components: { ModifyA, ModifyB },
      props: {
        value: {
          type: MyClass,
          required: true
        }
      },
      data() {
        return { object: this.value };
      },
      watch: {
        value(val) {
          this.object = val;
        },
        object(value) {
          this.$emit("input", value);
        }
      }
    };
    </script>
    

    由于观察者,每当父级更新value 时,object 变量就会更新。

    【讨论】:

      猜你喜欢
      • 2015-06-11
      • 2018-07-18
      • 1970-01-01
      • 2021-03-30
      • 1970-01-01
      • 1970-01-01
      • 2018-08-09
      • 2021-06-30
      • 2020-01-19
      相关资源
      最近更新 更多