站点图标 山维空间

Backbone.js经验两则

使用HTML5,实现从桌面拖拽到网页

使用HTML5新增加的API,可以很方便的实现拖拽, 包括从桌面拖拽到网页上(部分浏览器比如Chrome还可以把东西从网页拖拽到桌面),这个操作不在今天的讨论之内,可以参考:NATIVE HTML5 DRAG AND DROP这篇文章,讲得足够详细了。

当我试图在Backbone框架上使用这个功能的时候,问题出现了。开始我没多想,直接这么写的:

var myView = Backbone.View.extend({
  events: {
    "drop img": "img_dropHandler"
  },
  img_dropHandler: function (event) {
    var reader = new FileReader();
    var img = event.target;
    reader.onload = function (event) {
      $(img).attr('src', event.target.result);
    }
    result.readAsDataURL(event.dataTransfer.files[0]);
  }
});

结果运行时提示我,event对象没有dataTransfer属性。我用的是最新版本的Chrome,理应是对HTML5支持最好的,而且文中也说代码在Firefox和Chrome下运行通过。后来检查了一下event,发现是f.Event,似乎原本应该是MouseEvent或者Event什么的。于是我把属性展开,看到了originalEvent这个属性,是MouseEvent;再展开originalEvent,就看到了dataTransfer属性,里面有期望中的所有属性。看来是Backbone并没有直接使用原始事件,而是封装了一层再广播。(更正)事件代理是通过jQuery来做的,jQuery在这里把原始事件封装了一层再进行转播,导致原始事件的属性没有完全复制。解决方法很简单,多写几个字母就行了:

// 其它地方都一样
result.readAsDataURL(event.originalEvent.dataTransfer.files[0]);

Model中数组的处理

先看一段代码:

var ModelClass = Backbone.Model.extend({
  defaults: {
    contents: []
  }
});
var model1 = new ModelClass();
var arr = model1.get('contents');
arr[0] = 'haha';
var model2 = new ModelClass();
console.log(model2.get('contents'));

大家猜猜结果是什么?竟然是“[‘haha’]”!这个我只能认为是Backbone.js的bug了。解决方法是先复制一个数组,对数据操作后再赋值回去,如下:

var model1 = new ModelClass();
var arr = model1.get('contents').concat();
arr[0] = 'haha';
model1.set('contents', arr);
退出移动版