javascript - 在 momentjs 对象上更改事件触发

标签 javascript backbone.js underscore.js momentjs

对于我的一个项目,我正在监听模型对象的属性变化,并在其属性发生变化时调用 View 方法。

问题是我的模型的属性之一是 momentjs 日期对象。

我查看了 Backbone 源代码,它似乎使用下划线方法 _.isEqual() 触发了 setter 中的更改。

看完underscore documentation , isEqual 对两个对象进行深度比较。

看起来不错,但是 momentjs 对象包含初始格式信息,即使日期的实际值具有相同的含义,如果它来自不同的地方,它可能会被格式化不同,因此,被下划线深度比较认为不相等.

// initialize model
var today = moment().startOf('day');

var model = new Backbone.Model({
    start: today
});

// change event
model.on('change', function(e){
    // if property start has changed
    if(e.changed.hasOwnProperty('start')){
        // log it
        console.log('date changed');   
    }
});


// simulates input from user
var userInput = moment().startOf('day').format('DD/MM/YYYY');
model.set({
    // it's the same day as today and it shouldn't trigger a change !
    start: moment(userInput,'DD/MM/YYYY')
});

我该怎么办?

  • 在我的模型中存储 unix 时间戳而不是 momentjs 对象?这也意味着重构我的整个代码...
  • 找到一种方法来“覆盖” isEqual 当它是一个 momentjs 对象时?但我宁愿不修改下划线,修改 momentjs 似乎还可以。

最佳答案

您最好的选择可能是覆盖 model.set 方法以对某些属性执行自定义相等性检查。

让我们创建 EqualModels 作为包含覆盖的基类:

var EqualModels = Backbone.Model.extend({
    set: function(key, val, options) {
        if (!this.equals)
            return Backbone.Model.prototype.set.apply(this, arguments);

        //lifted from Backbone source code
        var attrs, attr, dropped, fn;
        if (key == null) return this;

        // Handle both `"key", value` and `{key: value}` -style arguments.
        if (typeof key === 'object') {
            attrs = key;
            options = val;
        } else {
            (attrs = {})[key] = val;
        }
        options || (options = {});

        //determine which attributes have a custom equality check and apply it
        dropped = [];
        for (attr in attrs) {
            fn = this.equals[attr];
            if (_.isFunction(fn)) {
                if (fn(this.attributes[attr], attrs[attr]))
                    dropped.push(attr);
            }
        }

        //remove the attributes that are deemed equal
        attrs = _.omit(attrs, dropped);

        return Backbone.Model.prototype.set.call(this, attrs, options);
    }
});

目标是确定属性是否具有 this.equals 中定义的相等性检查,将此函数应用于当前值和潜在值,如果值被认为是,则从集合属性中删除该属性相等。

然后你可以把你的模型写成

var M = EqualModels.extend({
    equals: {
        start: function(v1, v2) {
            if (typeof(v1)!==typeof(v2)) return false;
            return v1.format('DD/MM/YYYY')===v2.format('DD/MM/YYYY');
        }
    }
});

这里的 moment 对象仅在 DD/MM/YYYY 格式不同时更新。和一个演示 http://jsfiddle.net/Nwdf4/3/

关于javascript - 在 momentjs 对象上更改事件触发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20352846/

相关文章:

javascript - 支持命名空间 xml 的 AJAX 库

javascript - 每 X 秒检查一次 IF 语句,然后运行代码一次

javascript - 如何正确使用Promise.all?

javascript - 没有设置回调的主干保存

java - Vaadin 嵌入SWF

javascript - 在 backbone.js 中获取模型的属性

javascript - backbone.js 中的动态 el 值

javascript - 在给定的对象数组中搜索键并替换值;

Backbone.js 集合获取多个模型

javascript - underscore.js groupBy 子数组