[英]Why does vue.js not update the dom with datepicker using moment.js
我正在 vue.js 中編寫一個(非常)簡單的 datepicker 控件,使用 moment.js 來格式化和改變日期。
我遇到的問題是,即使在我單擊任一按鈕時修改了組件中的日期實例,顯示也不會更新。
我嘗試將其更改為簡單的整數而不是日期實例,並且按預期工作(DOM 已正確更新)
這是我為此提供的源代碼:
應用程序.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: {}
}
});
索引.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/
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 不是immutable
的,這意味着當您在 moment 對象上調用 add/subtract 函數時,它返回相同的 object ,並在更改屬性后。
關於 vue 的反應性有一些警告,並且由於Object.observe現在已過時,它無法跟蹤 javascript 對象是否在內部發生了更改,除非您克隆該對象並創建一個您需要的新對象。
問題是對 selectedDate 的引用永遠不會改變。 即使您在其上調用方法,它也是同一個對象。
這里的一種方法是以不同的格式存儲日期。 作為日期對象、數字等。然后,當您對其進行更改時,您可以生成該數據的新實例。
這是一個例子:
var datePicker = Vue.component("datePicker", { data: function() { return { selectedDate: moment().toDate() } }, template: `<div> <button v-on:click='decrement'><</button> {{formattedSelectedDate}} <button v-on:click='increment'>></button> {{selectedDate}} </div>`, methods: { increment: function () { var currentDate = moment(this.selectedDate); currentDate.add(1, "days"); this.selectedDate = currentDate.toDate(); }, decrement: function () { var currentDate = moment(this.selectedDate); currentDate.subtract(1, "Days"); this.selectedDate = currentDate.toDate(); } }, computed: { formattedSelectedDate: function() { return moment(this.selectedDate).format("YYYY-MM-DD"); } } }); var PointTracker = new Vue({ el: "#PointTracker", data: { date: 0 }, components: { datePicker } });
<div id="PointTracker"> <date-picker /> </div> <script src="https://unpkg.com/vue/dist/vue.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.17.1/moment.js"></script>
這是因為 moment 和 vue 都依賴於定義對象的 getter 和 setter,這會導致在你的情況下一個覆蓋另一個。 (因此更改參考有效,因為vm.selectedDate.set
被覆蓋,而vm.set
未被覆蓋)
從時刻的文檔:
Moment.js 使用重載的 getter 和 setter。
來自 vue 的文檔:
Vue 會遞歸地將其屬性轉換為 getter/setter 以使其“反應”。 對象必須是普通的:瀏覽器 API 對象和原型屬性等原生對象將被忽略。 經驗法則是數據應該只是數據 - 不建議觀察具有自己狀態行為的對象。
快速驗證:我在創建的小提琴 saurabh 中添加了console.log(this.selectedDate.get)
,記錄的函數是stringGet
中的moment.js
,然后我在我的項目中檢查了vm.foo
的get
,它是proxyGetter
這是一個reactiveGetter
的包裝器,都在vue.runtime.common.js
中。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.