【问题标题】:Using v-model with a prop on VUE.JS在 VUE.JS 上使用带有 prop 的 v-model
【发布时间】:2018-02-20 04:58:35
【问题描述】:

我正在尝试使用来自带有 v-model 的道具的数据,以下代码有效,但出现警告。

<template>
<div>
       <b-form-input v-model="value" @change="postPost()"></b-form-input>
</div>
</template>
<script>
    import axios from 'axios';
    export default {
        props: {
            value: String
        },
        methods: {
            postPost() {
                axios.put('/trajectory/inclination', {
                    body: this.value
                })
                    .then(response => {
                    })
                    .catch(e => {
                        this.errors.push(e)
                    })
            }
        }
    }
</script>

警告说:

"避免直接修改 prop,因为每当父组件重新渲染时,该值将被覆盖。相反,使用基于 prop 值的数据或计算属性。正在修改的 Prop:“value”

所以我改变了,现在我正在使用警告所说的数据。

<template>
<div>
       <b-form-input v-model="_value" @change="postPost()"></b-form-input>
</div>
</template>
<script>
    import axios from 'axios';

    export default {
        props: {
            value: String
        },
        data() {
            return {
                _value: this.value
            }
        },
        methods: {
            postPost() {
                axios.put('/trajectory/inclination', {
                    body: this._value
                })
                    .then(response => {
                    })
                    .catch(e => {
                        this.errors.push(e)
                    })
            }
        }
    }

所以现在代码不起作用并且警告说:

“属性或方法“_value”未在实例上定义,但在渲染期间被引用。确保在数据选项中声明反应数据属性”

知道如何修复第一个代码以抑制警告吗? (或者关于如何修复第二个代码的一些想法?)

Obs.: b-form-input 这不是我的组件,这是来自 Boostrap-Vue (Doc for b-form-input) 的文本输入

【问题讨论】:

    标签: vue.js vuejs2 vue-component


    【解决方案1】:

    答案来自https://github.com/vuejs/vue/issues/7434

    props 是只读的,但您正在尝试使用 v-model 更改其值。在这种情况下,如果您更改输入值,则不会修改 prop 并在下次更新时恢复该值。

    改用数据属性或计算设置器:

    computed: {
      propModel: {
        get () { return this.prop },
        set (value) { this.$emit('update:prop', value) },
      },
    },
    

    https://vuejs.org/v2/guide/computed.html#Computed-Setter

    【讨论】:

    • 另外,Vue2 不是说最好的做法不应该使用 $emit 吗?
    【解决方案2】:

    Bert 解决了您的直接问题,但我认为您也应该知道您的方法有点偏离。由于最终您将新值发送到postPost,因此您实际上不需要修改本地副本。使用发送到change 处理程序的event 对象从输入中获取当前值。

    不要使用v-model,而是使用:value,并且在指定change 处理程序时不要包含调用括号。

    <template>
    <div>
           <b-form-input :value="value" @change="postPost"></b-form-input>
    </div>
    </template>
    <script>
        import axios from 'axios';
        export default {
            props: {
                value: String
            },
            methods: {
                postPost(event) {
                    axios.put('/trajectory/inclination', {
                        body: event.target.value
                    })
                        .then(response => {
                        })
                        .catch(e => {
                            this.errors.push(e)
                        })
                }
            }
        }
    </script>
    

    【讨论】:

    • 感谢您的帮助,我认为您的方法对于获取修改后的值是一种很好的方法。我想添加一些我发现的东西如果有人想改变“prop”的值(比如双向绑定),正确的方法是使用修饰符同步 link 而不是 v-model
    • .sync 与v-model for components 非常相似。您可以使用任何一种。 v-model 专门用于 value 道具,而 .sync 可以与任何名称的道具一起使用。
    • 为了帮助任何人,我遇到了同样的问题。我刚刚将 v-model="" 中的 var 从 props 数组更改为 data。
    【解决方案3】:

    _ 前缀属性是 reserved 表示 Vue 的内部属性。

    以 _ 或 $ 开头的属性不会在 Vue 上代理 实例,因为它们可能与 Vue 的内部属性和 API 方法。

    尝试将 _value 更改为不以下划线开头的内容。

    【讨论】:

    • 谢谢 :) 我在 API 文档中找到并添加到答案中。
    • 感谢 Bert 的帮助,更改变量名使它像魅力一样工作。但正如 Roy 在他的回答中提到的那样,也许我使用局部变量的方法有点偏离,因为这个问题可供其他人使用,也许对他们来说最好采用另一种方法。
    【解决方案4】:

    一种通用的解决方法是引入一个数据变量并观察更新变量的道具。这是非常微妙的,很容易出错,所以这里有一个使用 v-model 的 Vuetify 模态示例(同样的技术,理论上,应该适用于 &lt;input&gt; 和其他):

    <template>
      <v-dialog v-model="isVisible" max-width="500px" persistent>
      </v-dialog>
    </template>
    
    <script>
    export default {
      name: 'Blablabla',
      props: {
        visible: { type: Boolean, required: true }
      },
      data() {
        isVisible: false
      },
      watch: {
        // `visible(value) => this.isVisible = value` could work too
        visible() {
          this.isVisible = this.$props.visible
        }
      }
    }
    </script>
    

    【讨论】:

      【解决方案5】:

      对于那些仍然坚持这一点的人,Vue 官方文档展示了如何在自定义组件上使用 v-model:https://vuejs.org/v2/guide/components.html#Using-v-model-on-Components

      TL;DR:

      您只需要有一个专门命名的value 道具,并在您为您实例化组件映射时发出input 事件v-model。

      更多信息请参见上面的链接。

      <template>
        <input
          type="text"
          :value="value"
          @input="$emit('input', $event.target.value)"
        />
      </template>
      
      <script>
      export default {
        name: "Input",
        props: {
          value: String,
        },
      };
      </script>
      
      <Input v-model="searchText"></Input>
      

      【讨论】:

        【解决方案6】:

        将您的输入 v-model 指令指向名为 value_ 的数据属性(或任何其他不以前缀 _ 或 $ 开头的名称,这些名称由 Vue 保留)。将数据属性的默认值设置为null。然后,添加一个方法getValue(),它将根据您的value 属性值设置属性value_。最后,在 Vue 的 created() 生命周期钩子中调用 getValue()。像这样:

        <template>
          <div>
            <b-form-input v-model="value_" @change="postPost()">
            </b-form-input>
          </div>
        </template>
        
        <script>
          import axios from 'axios';
          
          export default {
            data: () => ({
              value_: null
            }),
            props: {
              value: String
            },
            methods: {
              postPost() {
                axios.put('/trajectory/inclination', {
                  body: this.value_
                })
                .then(response => {
                })
                .catch(e => {
                  this.errors.push(e)
                })
              },
              getValue() {
                this.value_ = this.value;
              }
            },
            created() {
              this.getValue()
            }
          }
        </script>
        

        【讨论】:

          【解决方案7】:

          您可以使用如下数据。

          <template>
            <input type="text" v-bind:value="value" v-on:input="dValue= $event.target.value" />
          </template>
                  
           <script>
           export default {
            props: ["value"],
            data: function () {
              return {
                dValue: this.value,
              };
            },
            methods: {
              alertValue() {
               alert("Current Value" + this.dValue);
              },
            },
          };
          </script>
          

          【讨论】:

            猜你喜欢
            • 2018-06-04
            • 2017-11-14
            • 2015-11-02
            • 2020-06-07
            • 2020-01-01
            • 1970-01-01
            • 2019-05-07
            • 2020-07-18
            相关资源
            最近更新 更多