避免直接在VueJS 2中改变道具

时间:2017-03-05 21:25:54

标签: javascript vuejs2

首先,我刚刚开始玩VueJS,所以这不是VueJS版本的东西,如建议here

可能与以下内容重复:

我的问题始于我的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: ""
        }
    },

});

我在这里编写了代码:http://codepen.io/AngelinCalu/pen/OpXBay

然而,第二个答案来自:vuejs update parent data from child component让我意识到我错过了什么

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

在另一个示例中:Update a child's data component to the father component in vue.js using .vue webpack(vue2),答案建议添加watch以发出更改。

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

现在我更加困惑了!处理这个问题的正确(或最好)方法是什么?

注意: 如果我从最初的html

中删除
   :birthDay="birthDay"
   :birthMonth="birthMonth"
   :birthYear="birthYear"

它仍然按预期工作,但我仍然得到Vue警告,但是,如果我从这里跟踪方法:https://stackoverflow.com/a/41901150/2012740,它停止工作,但我没有得到任何错误。< / p>

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

总结:我从一开始就需要功能但没有[Vue warn]

这是我在最初的例子中得到的:

  

[Vue警告]:避免直接改变道具,因为只要父组件重新渲染,该值就会被覆盖。而是根据prop的值使用数据或计算属性。支持变异:“birthYear”

1 个答案:

答案 0 :(得分:3)

警告是将v-model设置为您的媒体资源的结果。原因是因为如果你改变了birthYear,birthMonth或birthDay outside 组件,那么无论当前里面的值是什么,组件都会立即被覆盖。

相反,请抓取副本。

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 ....
        }
    }

});

你几乎完全是在你的小提琴中这样做了,但是你没有更正你的计算值。

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
    }
},