避免在 VueJS 2 中直接修改 prop

Avoid mutating a prop directly in VueJS 2

首先,我刚开始玩 VueJS,所以这不可能是建议的 VueJS 版本

它可能与 :

重复

我的问题始于我的 Html 看起来像这样:

<div id="app">
  <div class="row">
    <div class="form-group col-md-8 col-md-offset-2">
      <birthday-controls
       :birthDay="birthDay"
       :birthMonth="birthMonth"
       :birthYear="birthYear">
      </birthday-controls>
    </div>
  </div>
</div>

和 JS:

Vue.component('birthday-controls', {

    template: `<div class="birthday">
    <input type="text" name="year"  placeholder="yyyy" v-model="birthYear" size="4" maxlength="4"/>
    <input type="text" name="month" placeholder="mm" v-show="validYear" v-model="birthMonth" size="3" maxlength="2"/>
    <input type="text" v-show="validYear && validMonth" name="day" placeholder="dd" v-model="birthDay" size="2" maxlength="2"/>
  </div>`,

    props: ['birthDay', 'birthMonth', 'birthYear'],

    computed: {
        validYear: function() {
            return (this.birthYear > new Date().getFullYear()-100 && this.birthYear < new Date().getFullYear()-14)
        },
        validMonth: function() {
            return (this.birthMonth > 0 && this.birthMonth <= 12)
        },
        validDay: function() {
            return (this.birthDay > 0 && this.birthDay <=31) //I have to add more checking here for february, leap years and ....
        }
    }

});

new Vue({
    el: '#app',

    data: function() {
        return {
            birthDay: "",
            birthMonth: "",
            birthYear: ""
        }
    },

});

我在这里准备了codepen:http://codepen.io/AngelinCalu/pen/OpXBay

然而,这里的第二个答案: 让我意识到我遗漏了一些东西

在那个例子中,它在其中一个方法中设置了一个 this.$emit('increment'),并在特定事件上触发它。

在另一个示例中:,答案建议添加 watch 以发出更改。

  watch: {
    val() {
      this.$emit('title-updated', this.val);
    }
  }

现在我更糊涂了!处理此问题的正确(或最佳)方法是什么?

注意: 如果我从最初的 html 中删除:

   :birthDay="birthDay"
   :birthMonth="birthMonth"
   :birthYear="birthYear"

它仍然按预期工作,但我仍然收到 Vue 警告,但是,如果我按照此处的方法进行操作:,它会停止工作,但我没有收到任何错误.

我的更新代码:https://jsfiddle.net/angelin8r/647m7vdf/

总而言之:我从一开始就需要功能,但没有 [Vue warn]

这是我在初始示例中得到的:

[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "birthYear"

该警告是将 v-model 设置为您的属性值的结果。原因是因为如果你改变 birthYear,birthMonth 或 birthDay outside 组件,那么无论值是当前 inside 组件将立即被覆盖.

相反,捕获一个副本。

Vue.component('birthday-controls', {

    template: `<div class="birthday">
    <input type="text" name="year"  placeholder="yyyy" v-model="internalBirthYear" size="4" maxlength="4"/>
    <input type="text" name="month" placeholder="mm" v-show="validYear" v-model="internalBirthMonth" size="3" maxlength="2"/>
    <input type="text" v-show="validYear && validMonth" name="day" placeholder="dd" v-model="internalBirthDay" size="2" maxlength="2"/>
  </div>`,

    props: ['birthDay', 'birthMonth', 'birthYear'],

    data(){
      return {
        internalBirthDay: this.birthDay,
        internalBirthMonth: this.birthMonth, 
        internalBirthYear: this.birthYear
      }
    },

    computed: {
        validYear: function() {
            return (this.internalBirthYear > new Date().getFullYear()-100 && this.internalBirthYear < new Date().getFullYear()-14)
        },
        validMonth: function() {
            return (this.internalBirthMonth > 0 && this.internalBirthMonth <= 12)
        },
        validDay: function() {
            return (this.internalBirthDay > 0 && this.internalBirthDay <=31) //I have to add more checking here for february, leap years and ....
        }
    }

});

您在 fiddle 中几乎完全做到了这一点,但您没有更正您的计算值。

computed: {
    validYear: function() {
        return (this.birthYear > new Date().getFullYear()-100 && this.birthYear < new Date().getFullYear()-14)
    },
    validMonth: function() {
        return (this.birthMonth > 0 && this.birthMonth <= 12)
    },
    validDay: function() {
        return (this.birthDay > 0 && this.birthDay <=31) //I have to add more checking here for february, leap years and stuff
    }
},

应该是

computed: {
    validYear: function() {
        return (this.var_birthYear > new Date().getFullYear()-100 && this.var_birthYear < new Date().getFullYear()-14)
    },
    validMonth: function() {
        return (this.var_birthMonth > 0 && this.var_birthMonth <= 12)
    },
    validDay: function() {
        return (this.var_birthDay > 0 && this.var_birthDay <=31) //I have to add more checking here for february, leap years and stuff
    }
},