使用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);
欢迎吐槽,共同进步