【问题标题】:How to solve [Vue warn]: Avoid mutating a prop directly since the value will be overwritten on vue.js 2?如何解决 [Vue 警告]:避免直接改变 prop,因为值会在 vue.js 2 上被覆盖?
【发布时间】:2017-07-20 05:19:24
【问题描述】:

我的看法是这样的:

<div class="col-md-8">
    ...
        <star :value="{{ $data['rating'] }}"></star>
    ...
</div>

我的明星组件是这样的:

<template>
    <span class="rating" :class='{"disable-all-rating": !!value}'>
        <template v-for="item in items">
            <label class="radio-inline input-star" :class="{'is-selected': ((starValue>= item.value) && starValue!= null)}">
                <input type="radio" class="input-rating" v-model="starValue" @click="rate(item.value)">
            </label>
        </template>
    </span>
</template>
<script>
    export default{
        props: {
            'value': null
        },
        computed: {
            starValue () {
                return this.temp_value
            }
        },
        data(){
            return{
                items: [
                    {value: 5},
                    {value: 4},
                    {value: 3},
                    {value: 2},
                    {value: 1}
                ],
                temp_value: null,
            }
        },
        methods:{
            rate: function (star) {           
               this.$http.post(window.BaseUrl + '/star', {star: star});                         
               this.temp_value = star;                         
            },
        }
    }
</script>

我的css是这样的:

span.rating {
  direction: rtl;
  display: inline-block;
}

span.rating .input-star {
  background: url("../img/star.png") 0 -16px;
  padding-left: 0;
  margin-left: 0;
  width: 16px;
  height: 16px;
}

span.rating .input-star:hover, span.rating .input-star:hover ~ .input-star {
  background-position: 0 0;
}

span.rating .is-selected{
   background-position: 0 0;
}

span.rating .is-disabled{
   cursor: default;
}

span.rating .input-star .input-rating {
  display: none;
}

当我点击星号时,控制台上存在这样的错误:

[Vue 警告]:避免直接改变一个 prop,因为它的值会是 每当父组件重新渲染时被覆盖。相反,使用 基于道具值的数据或计算属性。道具存在 突变:“价值”(在 C:\xampp\htdocs\myshop\resources\assets\js\components\Star.vue)

我该如何解决?

【问题讨论】:

    标签: javascript vue.js vuejs2 vue-component


    【解决方案1】:

    您正在此处更改 value 属性。

    return this.value = star;
    

    可能在这里。

    v-model="value"
    

    警告意味着每当您的视图重新渲染时,value 属性将被设置为 $data['rating'],覆盖您在启动组件中所做的任何事情。

    当有人单击星号时,您可能希望$emit 该组件已更改并让您的视图更改$data['rating'],而不是更改组件内的属性,这将正确地重新渲染星形组件。

    请参阅有关 component composition 的 Vue 文档。

    【讨论】:

    【解决方案2】:

    警告建议不要直接修改 prop 的值,否则如果父组件的数据发生更改,无论如何都会丢失更改。

    也就是说,在你的方法中:

    methods: {
      rate: function (star) {
        var self = this;
        if (!this.disabled) {
            this.$http.post(window.BaseUrl + '/star', {star: star}).then(function (response) {
                console.log('submitted');
            });
            this.temp_value = star;
            // return this.value = star; - remove this line
        }
      }
    }
    

    并像这样添加computed 属性:

    computed: {
      starValue () {
        return this.temp_value
      }
    }
    

    【讨论】:

    • 我试过了。但是,它会影响其他代码。你能用更完整的方式更新你的答案吗?
    • @samueltoh 你能告诉我你是如何使用value的吗?为什么它会影响其他地方?
    • 看我的问题。我更新代码。我试试这样
    • @samueltoh 抱歉,但我无法看到您在哪里使用价值,对于您的情况,您需要使用 v-model 但是如何,只有当我了解您当前的使用情况时,我才能提供帮助.
    • 这个:props: { 'value': null },。这就是价值。我已经更新了我的代码。我已根据您的回答更新了我的代码。我的代码也使用了 v-model
    【解决方案3】:

    您需要使用 getter 和 setter 进行计算,然后使用 $emit 更新属性,例如:

        computed: {
            starValue:{ 
                get:function () {
                    return this.temp_value
                },
                set: function(newValue){
                    // $emit is the correct way to update props:
                    this.$emit('update:value', newValue);
                }
            }
        }
    

    【讨论】:

      猜你喜欢
      • 2020-09-11
      • 2021-03-02
      • 2020-09-12
      • 2019-04-03
      • 2017-03-27
      • 2019-08-19
      • 2021-09-05
      • 2017-11-28
      • 2019-09-17
      相关资源
      最近更新 更多