Vue 3 删除组件道具反应性

Vue 3 remove component prop reactivity

我有 EditTransaction 组件并像这样调用它:

<edit-transaction
    v-if="editableTransaction.id === transaction.id"
    :key="'transaction'+transaction.id+etcount"
    :class="{'bg-red-300': type === 'expense', 'bg-green-300': type === 'income'}"
    :groups-prop="modelValue"
    :transaction="transaction"
    class="planning-transactions-item px-10 rounded-2xl w-[90%]"
    @close="editableTransaction = {id: null}">
</edit-transaction>

如您所见,我在其中发送了一个交易对象。由于这是一个编辑器,我不希望事务对象是反应性的。如果有人关闭了编辑器,我想要原始的事务对象而不是一些修改过的对象,所以如果我是正确的并且想删除代理我把它放在编辑器中:

const form = toRaw(props.transaction)

在编辑器模板中,有一些资产组件,其 v-model 值绑定到表单对象

<div class="flex gap-5 w-full">
    <FormInput id="et-date" v-model="form.due_date" class="et-fields tw-fields w-[150px]"
               placeholder="Date"
               type="date"
               @keyup.enter="saveChanges"></FormInput>
    <FormInput id="et-name" v-model="form.name" class="et-fields tw-fields" placeholder="Name"
               @keyup.enter="saveChanges"></FormInput>
    <FormInput id="et-value" v-model="form.value" class="et-fields tw-fields" mask-thousand
               placeholder="Value"
               @keyup.enter="saveChanges"></FormInput>
</div>

问题是,当我更改事务名称时,表单对象会更改,但事务属性也会更改。因此,名称也会在父数据中更改,因为交易道具是反应性的。 我做错了什么或者我怎样才能拥有一个表单对象,该表单对象的值在组件创建时用 props 值填充并且没有任何代理?

使用道具将初始值传递给子组件的状态是很常见的。这意味着您在本地 data 中“复制”了一个 prop 的值。它使 prop 值免受意外更改的影响:Read more in Vue docs

这是一个非常简单的示例,展示了上述方法:

/your-child-component-vue/

export default {
  props: ['initialCounter'],
  data() {
    return {
      // counter only uses this.initialCounter as the initial value;
      // it is disconnected from future prop updates.
      counter: this.initialCounter
    }
  }
}

现在,阅读您的示例,我发现您正在尝试更新表单中的一些数据,并且您不想更改初始信息,除非通过按钮或其他方式确认。解决这个问题的流程是:

  • 将用户可能更改的初始数据作为道具传递。
  • 如果用户通过输入元素更改了一些数据但没有确认这些更改(通过按钮)保持数据不变(这意味着您不会向父级发送任何更改,保持道具值不变)
  • 如果用户更改了一些数据并进行了确认,则将此更新后的数据发送给父级 (this.$emit),以便它知道这些更改。

所以我找到了两个解决方案:

const form = reactive({...props.transaction})

const form = Object.assign({}, props.transaction)

两者都有效,而且当我更改表单值时,它不会改变 prop。