简体   繁体   English

Vue.js 更新的属性在子组件上没有改变

[英]Vue.js updated property doesn't change on child component

I have a child component which is an HTML input element.我有一个子组件,它是一个 HTML 输入元素。 It looks like this:它看起来像这样:

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

LabelInput.vue file: LabelInput.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});
    }
}

So the model is passed via filters.productId.value as data and then changed into local variable inputData.因此 model 作为数据通过 filters.productId.value 传递,然后更改为局部变量 inputData。

Now if I change the input value I use updateValue function which emits the input name and it's value back into parent component, which updates the original filters.productId.value value.现在,如果我更改输入值,我将使用 updateValue function 发出输入名称并将其值返回到父组件,从而更新原始的 filters.productId.value 值。 This works fine.这很好用。

Now the problem is that I have a function on my parent component which resets the filters.productId.value value back to null. It looks like this:现在的问题是我的父组件上有一个 function,它将 filters.productId.value 值重置回 null。它看起来像这样:

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

And now the data in my child component LabelInput doesn't change, even though filters.productId.value is null now.现在我的子组件 LabelInput 中的数据没有改变,即使 filters.productId.value 现在是 null。 How do I refresh the child component?如何刷新子组件?

I did not work with Vue as a class component yet, but it seems that the problem is setting the prop to a attribute in the class.我还没有将 Vue 作为 class 组件使用,但问题似乎是将 prop 设置为 class 中的属性。

private inputData = this.data

Vue listens to prop changes, but data does not listen for referenced changes, so the prop has changed, but not inputData because Vue doesn't set listeners for it. Vue 监听 prop 的变化,但 data 不监听引用的变化,所以 prop 变了,但inputData没有变,因为 Vue 没有为它设置监听器。

Working without classes when I want to do something similar as you, I use the computed properties.当我想做与您类似的事情时,不用类工作,我使用computed属性。 Check the docs to see how it is implemented.检查文档以了解它是如何实现的。

Using a computed property.使用计算属性。

get inputData() {
  return this.data;
}

I believe this will work as you expect.我相信这会如您所愿。

To better visualize what we are saying in the comments, here's how the code should look like without v-model.为了更好地可视化我们在评论中所说的内容,下面是没有 v-model 的代码应该是什么样子。

input:输入:

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

Getter:吸气剂:

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:更新值:

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

Also, I don't see the need to use $root , since you can use the $emit in the component.另外,我认为不需要使用$root ,因为您可以在组件中使用$emit For non class components you access it through this.$emit , I believe here should be the same.对于非 class 组件,您可以通过this.$emit访问它,我相信这里应该是一样的。

Another change you could do is to listen for the event in the html:您可以做的另一个更改是监听 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"

/>

You can declare a method named doSomething that takes the received value as the first argument or simply set the variable to the value received by the event @updateValue="(value) => {filters.productId.value = value}" .您可以声明一个名为doSomething的方法,该方法将接收到的值作为第一个参数,或者简单地将变量设置为事件接收到的值@updateValue="(value) => {filters.productId.value = value}" This will work as well.这也会起作用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM