【问题标题】:Vue.js component design - how to clear a prop when input changes without mutating the prop?Vue.js 组件设计 - 如何在输入更改时清除道具而不改变道具?
【发布时间】:2020-09-22 23:03:43
【问题描述】:

在我们的 Vue.js 应用程序中,我们有一堆组件负责渲染与特定字段相关的所有内容。比如我们的一个组件叫做SelectField,负责渲染一个<select>元素,以及一个<label>,错误信息等等。

目前错误消息是在组件上定义的道具,如下所示:

props: {
   ...,
   errorMessage: String
}

如果值 errorMessage 是真实的,我们会显示错误。如果不是,我们不会。像这样的:

<p v-if="errorMessage">{{ errorMessage }}</p>

errorMessage 的值是在用户单击按钮时在父组件中计算的。按钮代码运行一些验证逻辑,如果验证失败,该字段的 errorMessage 将设置为适当的消息。像这样的:

export default {
    data() {
        return {
            exampleError: ""
        }
    },
    methods: {
        validate() {
            if (...) {
                exampleError = "You got an error";
            }
        }
    }
}

我要解决的问题是如何在用户对组件进行更改时清除错误消息。目前我正在通过这样做来解决它:

<SelectField
    ...
    :errorMessage="exampleError"
    @input="exampleError = ''"
/>

本质上,它通过@input 监听SelectField 的变化,然后将错误消息设置为空。

这行得通,除了我必须把它放在我使用该组件的任何地方。我不能让它成为组件内部的一部分,因为errorMessage 是一个道具,而变异道具是一种反模式。

有什么方法可以让这个功能成为组件的责任而不改变道具?

【问题讨论】:

    标签: vue.js vue-component


    【解决方案1】:

    使用 watcher 监听 prop 的变化,并将新值设置为错误消息的本地副本。

    当您的组件更新其状态时,您可以清除本地副本。

    export default {
      props: { errorMessage: String },
      data: () => ({ error: this.errorMessage }), // initialise with the prop value
      watch: {
        errorMessage (newValue) {
          this.error = newValue // update the local error message when the prop changes
        }
      }
    }
    

    在你的模板中

    <p v-if="error">{{ error }}</p>
    <select @input="error = null"> <!-- ? just an example -->
    </select>
    

    【讨论】:

    • 这是否与直接修改道具相同,因为一旦父级更改了值,它将被覆盖?如果是这种情况,这种情况是否可以接受变异道具的使用(即,我们希望对其进行变异,直到父级再次更改它)?
    • @Caleb 不,这里的道具没有变异。将其视为组件保持其内部状态,直到它从其父级获得更新消息
    【解决方案2】:

    您可以将属性添加到您的道具。

    试试这个:

    props: 
    {
       errorMessage:
       { 
         type: String,
         deep: true,
         immediate: true 
       }
    }
    

    这里的关键是 deep:trueimmediate:true。他们基本上强迫道具观察任何变化。

    【讨论】:

    • 你能链接到这个文档吗?我认为您混淆了propswatch
    • 我真的很抱歉。有趣的是,我多次使用了我建议的方法,并且效果很好。您可以自己尝试一下,如果失败,您可以明确使用观察者的 deep:true 和 immediate:true 道具
    猜你喜欢
    • 2017-04-08
    • 2023-03-27
    • 1970-01-01
    • 2021-11-03
    • 2020-06-17
    • 2018-08-09
    • 2018-10-28
    • 2018-07-02
    • 1970-01-01
    相关资源
    最近更新 更多