backbone框架之model事件触发误区

发表于 2017-01-12
更新于 2024-05-23
分类于 技术专栏
阅读量 6602
字数统计 2471

前言

在使用swagger UI的时候发现他们代码用的是backbone,之后应组织要求,改版swagger UI并添加我们的需求,于是就不得不开始接触backbone框架了。不过没有全面系统地学习这个框架,只是在添加新需求的时候遇到几个问题,这里拿出来分享一下。

1.关于backbone model的事件触发

如果你定义了一个model如下:(基于swagger UI)

SwaggerUi.Models.ProjectModel = Backbone.Model.extend({
    defaults: {
      data: []
    },
    url: '/listAll',
    initialize: function () {
      this.fetch();
      this.on('change', this.validate);
    },

    validate: function () {
        return true;
    }
});

data属性是一个对象数组,如果这个时候你需要往data数组添加一个新的数据,很有可能你会这么写:

var old = ProjectModel.get('data');
ProjectModel.set({'data': old.push(newdata)});

或者:

var old = ProjectModel.get('data');
old.push(newdata)
ProjectModel.set({'data': old});

然后你期望的这些操作应该会自动触发change事件的并且数据有被更新,但事实并不能如愿。这是为什么呢?

先说说第一种情况:

这种写法的错误在于没有搞清push这个API的返回值。在MDN中明确指出其返回值是新数组的长度,而不是整个新数组,所以第一种情况肯定是改变不了data的值。

再说说第二种情况:

现在已经是先执行push了,再重新set,但是为什么不会触发change事件呢?原因是在backbone使用UnderScore的isEqual来判断新值与旧值,细节可以看实现代码backbone.js#L347,所以对于那些类型不可变的属性比如number、strings、booleans来说这样是没问题的,但是如果对于数组或者对象这种不定类型的属性这个判断就会失效的了,因为你简单地新增或者修改数组中的某一个item,但最后新旧值比较依然会相等的。

因此正确的解决办法有如下几种:

var old = ProjectModel.get('data');
old.push(newdata)
ProjectModel.unset( "data", { silent: true } );
ProjectModel.set({'data': old});

当unsetting属性的时候通过设置silent: truechange事件只会被触发一次(当set()方法被调用并且属性被更新了)

var old = _(ProjectModel.get('data')).clone()
old.push(newdata)
ProjectModel.set({'data': old});
var old = ProjectModel.get('data');
old.push(newdata)
ProjectModel.set({'data': old});
ProjectModel.trigger('change'); // 手工去触发change事件

附带

实在不知道把这个关于Mongoose的小常识放在哪里,姑且当在这边吧:

如何在遍历document的时候忽略某个特定的字段?

答案: 只需要在你想要排除的字段名前面加上-即可,比如:

const populateOption = {
  path: 'files',
  select: 'name versions -_id',
  populate:{path: 'versions', select: 'version -_id'}

};
return project.find().select('name files -_id').populate(populateOption).exec()

这个populate是为了排除_id这个字段,所以在其前面加了-这个标记。

参考

  1. http://underscorejs.org/#isEqual
  2. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push
  3. http://stackoverflow.com/questions/11661380/does-backbone-models-this-get-copy-an-entire-array-or-point-to-the-same-array/11662381#11662381

公众号关注一波~

微信公众号

关于评论和留言

如果对本文 backbone框架之model事件触发误区 的内容有疑问,请在下面的评论系统中留言,谢谢。

网站源码:linxiaowu66 · 豆米的博客

Follow:linxiaowu66 · Github