为什么vue.js不使用moment.js使用datepicker更新dom

Pat*_*ick 6 javascript vue.js

我在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'>&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: {}
    }
});
Run Code Online (Sandbox Code Playgroud)

的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>
Run Code Online (Sandbox Code Playgroud)

Sau*_*abh 10

您必须更改selectedDatemoment函数返回的引用,它们始终具有相同的引用,因此不会触发vue观察器.

您必须进行以下更改才能更改参考:

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

工作小提琴: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);
}
Run Code Online (Sandbox Code Playgroud)

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


为什么会这样

之所以发生这种情况是因为moment.js 不是immutable,它意味着当你在一个时刻对象上调用加/减函数时,它会在更改属性后返回相同的对象.

关于vue的反应性有一些警告,因为Object.observe现在已经过时,它无法跟踪javascript对象是否在内部发生了变化,除非你克隆对象并创建一个你需要的新对象.

还有其他解决方法,包括使用冻结矩库.