为什么 vue.js 不使用 moment.js 使用 datepicker 更新 dom [英] Why does vue.js not update the dom with datepicker using moment.js

查看:45
本文介绍了为什么 vue.js 不使用 moment.js 使用 datepicker 更新 dom的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在 vue.js 中编写一个(非常)简单的 datepicker 控件,使用 moment.js 来格式化和改变日期.

我遇到的问题是,即使在我单击任一按钮时修改了组件中的日期实例,显示也不会更新.

我尝试将其更改为简单整数而不是日期实例,并且按预期工作(DOM 已正确更新)

这是我的源代码:

App.js

Vue.component("datePicker", {道具:[价值"],数据:函数(){返回 { selectedDate: moment(this.value) };},模板:"<div><button v-on:click='decrement'><</button>{{formattedSelectedDate}}<button v-on:click='increment'>&&;gt;</button></div>",方法: {增量:函数(){this.selectedDate.add(1, "天");this.$emit('input', this.selectedDate);},递减:函数(){this.selectedDate.subtract(1, "天");this.$emit('input', this.selectedDate);}},计算:{格式化选择日期:函数(){return this.selectedDate.format("YYYY-MM-DD");}}});var PointTracker = new Vue({el: "#PointTracker",数据: {选择日期:时刻(),待办事项:{}}});

索引.html

<头><meta charset="utf-8"><title>点跟踪器</title><link rel="stylesheet" href="style.css"><身体><div id="PointTracker"><date-picker v-model="selectedDate">

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

解决方案

selectedDate 的引用必须修改,因为它是从 moment 函数返回的,它们是始终具有相同的引用,因此不会为这些触发 vue 观察者.

您必须进行以下更改才能更改引用:

方法:{增量:函数(){this.selectedDate = moment(this.selectedDate).add(1, "days")},递减:函数(){this.selectedDate = moment(this.selectedDate).subtract(1, "days")}},

工作小提琴:http://jsfiddle.net/mimani/pLcfyrvy/1/

<小时>

以下是add/的实现从 moment 库中减去:

function addSubtract(持续时间,输入,值,方向){var other = createDuration(input, value);duration._milliseconds += 方向 * other._milliseconds;持续时间._天 += 方向 * 其他._天;持续时间._月 += 方向 * 其他._月;返回持续时间._bubble();}//仅支持 2.0 样式的 add(1, 's') 或 add(duration)导出函数添加(输入,值){return addSubtract(this, input, value, 1);}//仅支持 2.0 样式的减法(1,'s')或减法(持续时间)导出函数减去(输入,值){return addSubtract(this, input, value, -1);}

它返回相同的对象,因此日期对象的引用是相同的.

<小时>

为什么会发生

发生这种情况是因为 moment.js 是一个 isn't immutable,它的意思是当你在moment对象上调用add/subtract函数时,它返回相同的对象,更改属性后.

警告vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats" rel="noreferrer">反应性 vue 和 Object.observe 现在已过时,它无法跟踪 javascript 对象是否在内部发生了更改,除非您克隆该对象并创建在您的情况下需要的新对象.

还有其他解决方法也适用于此包括使用 frozen-moment 库.

I am writing a (very) simple datepicker control in vue.js, using moment.js for formatting and mutating the date.

The problem I'm having is that even though the date instance in the component is modified when I click either button, the display does not update.

I've tried changing this to a simple integer instead of a date instance, and that works as expected (the DOM is updated properly)

Here is the source code that I have for this:

App.js

Vue.component("datePicker", {
    props: ["value"],
    data: function() {
        return { selectedDate: moment(this.value) };
    },
    template: "<div><button v-on:click='decrement'>&lt;</button>{{formattedSelectedDate}}<button v-on:click='increment'>&gt;</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>

解决方案

You have to change the reference of selectedDate, as it is returned from moment functions, they are always of same reference, so vue watchers are not triggered for these.

You have to make following changes to change the reference:

methods: {
    increment: function () {
        this.selectedDate = moment(this.selectedDate).add(1, "days")
    },
    decrement: function () {
        this.selectedDate = moment(this.selectedDate).subtract(1, "days")
    }
},

Working fiddle: http://jsfiddle.net/mimani/pLcfyrvy/1/


Following is implementation of add/subtract from moment library:

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);
}

It returns the same object so the reference is same for the date object.


Why It happened

It happens because moment.js is a isn't immutable, what it means is when you call add/subtract function on a moment object, it returns the same object, with after changing the properties.

There are some caveats on reactivity of vue and as Object.observe is obsolete now, it can not track if an javascript object has changed internally, unless you clone the object and create a new object which is needed in your case.

There are other workarounds also for this including using frozen-moment library.

这篇关于为什么 vue.js 不使用 moment.js 使用 datepicker 更新 dom的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆