我正在vue.js中编写一个(非常)简单的datepicker控件,使用moment.js格式化和更改日期。
我遇到的问题是,即使当我单击任一按钮时修改了组件中的日期实例,显示也不会更新。
我尝试将其更改为简单的整数而不是日期实例,并且按预期工作(DOM已正确更新)
这是我为此的源代码:
App.js
Vue.component("datePicker", {
props: ["value"],
data: function() {
return { selectedDate: moment(this.value) };
},
template: "<div><button v-on:click='decrement'><</button>{{formattedSelectedDate}}<button v-on:click='increment'>></button></div>",
methods: {
increment: function () {
this.selectedDate.add(1, "days");
this.$emit('input', this.selectedDate);
},
decrement: function () {
this.selectedDate.subtract(1, "days");
this.$emit('input', this.selectedDate);
}
},
computed: {
formattedSelectedDate: function() {
return this.selectedDate.format("YYYY-MM-DD");
}
}
});
var PointTracker = new Vue({
el: "#PointTracker",
data: {
selectedDate: moment(),
todoItems: {}
}
});
Index.html
<html>
<head>
<meta charset="utf-8">
<title>Point Tracker</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id="PointTracker">
<date-picker v-model="selectedDate">
</div>
<script src="node_modules/moment/moment.js"></script>
<script src="node_modules/vue/dist/vue.js"></script>
<script src="node_modules/vue-resource/dist/vue-resource.js"></script>
<script src="app.js"></script>
</body>
</html>
最佳答案
您必须更改selectedDate
的引用,因为它是从moment
函数返回的,它们始终是相同的引用,因此不会为这些触发vue观察者。
您必须进行以下更改才能更改引用:
methods: {
increment: function () {
this.selectedDate = moment(this.selectedDate).add(1, "days")
},
decrement: function () {
this.selectedDate = moment(this.selectedDate).subtract(1, "days")
}
},
工作提琴:http://jsfiddle.net/mimani/pLcfyrvy/1/
以下是add/subtract库中moment的实现:
function addSubtract (duration, input, value, direction) {
var other = createDuration(input, value);
duration._milliseconds += direction * other._milliseconds;
duration._days += direction * other._days;
duration._months += direction * other._months;
return duration._bubble();
}
// supports only 2.0-style add(1, 's') or add(duration)
export function add (input, value) {
return addSubtract(this, input, value, 1);
}
// supports only 2.0-style subtract(1, 's') or subtract(duration)
export function subtract (input, value) {
return addSubtract(this, input, value, -1);
}
它返回相同的对象,因此对日期对象的引用相同。
为什么发生
之所以会发生这种情况,是因为moment.js是isn't
immutable
,这意味着在更改属性之后,在带有矩值的对象it returns the same object上调用添加/减去函数。vue的caveats上有一些reactivity,由于Object.observe现在已过时,因此无法跟踪javascript对象是否在内部进行了更改,除非您克隆该对象并创建您需要的新对象。
还有其他的workarounds,包括使用frozen-moment库。