首页 > 解决方案 > Vue.js 更新的属性不会在子组件上更改

问题描述

我有一个子组件,它是一个 HTML 输入元素。它看起来像这样:

<label-input inputId="formProductId"
             inputType="number"
             inputName="productId"
             :inputEnabled="filters.productId.options"
             :label="translations['product_id']"
             :placeholder="translations['product_id']"
             :data="filters.productId.value"
/>

标签输入.vue 文件:

<template>
    <div class="form-element">
        <label :for="inputId" :class="['form-element-title', { 'js-focused': focused }]">{{ label }}</label>
        <input @input="updateValue($event.target.value)" :type="inputType" :id="inputId" :name="inputEnabled ? inputName : false" v-model="inputData" :placeholder="placeholder" @focus="focused = true" @blur="focused = false">
    </div>
</template>

<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';

@Component
export default class LabelInput extends Vue {
    @Prop({ default: () => '' }) inputId!: string
    @Prop({ default: () => '' }) inputType!: string
    @Prop({ default: () => '' }) inputName!: string
    @Prop({ default: () => '' }) label!: string
    @Prop({ default: () => '' }) placeholder!: string
    @Prop({ default: () => {} }) data!: []
    @Prop({ default: () => true }) inputEnabled!: string

    private inputData = this.data
    private focused = false

    updateValue (value: string) {
        this.$root.$emit('input', {'inputName' : this.inputName, 'inputValue' : value});
    }
}

所以模型通过filters.productId.value作为数据传递,然后变成局部变量inputData。

现在,如果我更改输入值,我将使用 updateValue 函数,该函数将输入名称及其值返回到父组件,从而更新原始 filters.productId.value 值。这工作正常。

现在的问题是我的父组件上有一个函数,它将filters.productId.value 值重置回null。它看起来像这样:

clearFilters() {
    for (const [key, value] of Object.entries(this.filters)) {
        this.filters[key].value = null;
    }
}

现在我的子组件 LabelInput 中的数据没有改变,即使 filters.productId.value 现在为空。如何刷新子组件?

标签: javascripttypescriptvue.jsvue-component

解决方案


我还没有将 Vue 用作类组件,但似乎问题在于将 prop 设置为类中的属性。

private inputData = this.data

Vue 监听 prop 的变化,但是 data 不监听引用的变化,所以 prop 发生了变化,但不是inputData因为 Vue 没有为它设置监听器。

当我想做与您类似的事情时,我会使用computed属性而不使用类。检查文档以了解它是如何实现的。

使用计算属性。

get inputData() {
  return this.data;
}

我相信这会如你所愿。

为了更好地可视化我们在评论中所说的内容,下面是没有 v-model 的代码应该是什么样子。

输入:

<input :value="inputData" @input="updateValue($event.target.value)" :type="inputType" :id="inputId" :name="inputEnabled ? inputName : false" :placeholder="placeholder" @focus="focused = true" @blur="focused = false">

吸气剂:

get inputData() {
  // you can change your prop here and return a new value. 
  // A lower or upper case, for example. Just don't change the prop, only use it.
  return this.data;
}

更新值:

updateValue(value) {
  this.$root.$emit('input', {'inputName' : this.inputName, 'inputValue' : value});
    }
}

另外,我认为不需要使用$root,因为您可以$emit在组件中使用。对于非类组件你通过它访问this.$emit,我相信这里应该是一样的。

您可以做的另一个更改是在 html 中监听事件:

<label-input inputId="formProductId"
             inputType="number"
             inputName="productId"
             :inputEnabled="filters.productId.options"
             :label="translations['product_id']"
             :placeholder="translations['product_id']"
             :data="filters.productId.value"
             @updateValue="doSomething"

/>

您可以声明一个名为的方法doSomething,它将接收到的值作为第一个参数,或者简单地将变量设置为事件接收到的值@updateValue="(value) => {filters.productId.value = value}"。这也将起作用。


推荐阅读