Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/411.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 更改momentjs对象上的事件触发_Javascript_Backbone.js_Underscore.js_Momentjs - Fatal编程技术网

Javascript 更改momentjs对象上的事件触发

Javascript 更改momentjs对象上的事件触发,javascript,backbone.js,underscore.js,momentjs,Javascript,Backbone.js,Underscore.js,Momentjs,对于我的一个项目,我正在监听模型对象的属性更改,并在其属性更改时调用视图方法 问题是我的模型的属性之一是momentjs日期对象 我查看了主干源代码,它似乎使用下划线方法\uu.isEqual()触发setter中的更改 阅读后,isEqual对两个对象进行深入比较 看起来没问题,但momentjs对象包含初始格式信息,即使日期的实际值具有相同的含义,如果它来自不同的地方,它的格式可能会不同,因此,通过下划线深度比较可以认为不相等 // initialize model var today =

对于我的一个项目,我正在监听模型对象的属性更改,并在其属性更改时调用视图方法

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

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

阅读后,
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对象?这也意味着重构我的整个代码
  • 当它是momentjs对象时,是否找到一种“覆盖”
    isEqual
    ?但我不想修改下划线,尽管修改momentjs似乎还可以

正如nikoshr所提到的,这实际上不应该引起太大的关注,因为只有在执行设置或获取时才会触发事件,并且在这两种情况下,都可以使用{silent:true}选项使事件静音。因此,如果您控制了可能对日期进行更新的位置,您可以在此处实现自己的比较方法来决定它是否应该是静默的,这样就不需要修改momentjs、下划线或您的模型


也就是说,我相信您的第一种方法实际上是“正确的”,因为在模型值中包含对象实例可能不是一个好主意,因为主干不会自动序列化它们。我觉得在模型和模型的parse()中存储时间戳或任何包含所有相关信息的简单时间表示形式会更干净,将其转换为MomentJs对象并将其存储在对象的属性中。这意味着它不会通过model.get('momentJsObject')而通过model.momentJsObject可用,并且您仍然可以使用get('rawmonent')访问源数据,准备序列化回服务器。当然,这取决于具体情况,这只是一种“一般情况”的参考。

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

让我们创建
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');
        }
    }
});

此处,仅当DD/MM/YYYY格式不同时,才会更新矩对象。还有一个演示

我不确定我是否理解你的问题。主干仅在显式设置/重置值时触发更改事件,它不监视底层变量。或者你可以设置一个演示,比如说来说明你的担忧?@nikoshr这里有一把我的意思:你应该查看我在nikoshr评论中发布的小提琴,以便更好地理解我的意思。无论如何,您关于不存储momentjs对象的陈述似乎是正确的,但是操作已经初始化的momentjs对象比在每次访问/在每个局部视图中总是从unix时间戳重新初始化它更容易、更快。关于序列化部分,我正在使用我自己手工制作的同步,所以它不会真正困扰我。