Backbone.js笔记

关于Backbone的笔记。

关于事件

  • 使用Backbone里,我们可以继承Backbone.View,并且侦听UI事件。这些操作是通过jQuery或者Zepto的事件委托实现的,所以很重要的一点就是:这些事件都是UI事件,loaderror这些事件是无法在events属性里注册并被侦听到的。
  • 因为是托管的事件,事件处理函数最好用event.currentTarget来寻到节点
  • model的事件都会被collection转发,所以可以直接侦听collection;同理,除非remove并等待垃圾回收的model,也不应简单的调用off(),因为这会使collection没法侦听到事件,漏掉一些处理。

路由解析规则

这点文档中说得不算太详尽,我摸索如下:

  1. 路径分析以#/为起始,所以链接应该如#/app/add
  2. /是很重要的分隔符,末尾的/会被认为有下一级参数,比如app/list/的规则就不适用于http://domain.com/#/app/list这样的路径
  3. 规则只匹配一次,不会多次执行
  4. 刷新页面的方法:
    Backbone.history.loadUrl(Backbone.history.fragment);

其它关于Backbone.js的文章

Backbone.js经验两则

重写Backbone.js的加载动作

Mobile Web开发笔记

这里记录使用Phonegap开发移动应用期间发现的一些注意事项。

这里记录使用Phonegap开发移动应用期间发现。

性能

使用jQuery托管事件对阻止冒泡的影响

表现

解决 iOS webkit 使用CSS动画时闪烁的问题

CSS 兼容性

CSS 属性 iOS Android IE 其它
border-radius 3.x -webkit- Firefox 3.6- -moz-
Safari 4- -webkit-
box-shadow 2.3 -webkit- Safari 5- -webkit-

网摘

Developing Better PhoneGap Apps: Float Mobile Learning

重点包括

  1. 使用tap取代click(这点我还需要进一步测试,我发现zepto+phonegap没法捕获tap事件,不知道是我不是敲键盘的姿势不对)
  2. 使用css动画取代js动画

随记

  1. “click”和“tap“不是一回事儿,“click”会延迟300~400ms才处理,时间上会接近taphold之类的事件,“tap”更快
  2. 给元素加上:active伪类,可以给用户更快的反馈
  3. 调试不太容易,debug.phonegap.com似乎已经关了,得想办法把自己的weinre服务搭起来。暂时可以在js里写console.log(),接受一个参数,会在log cat输出。

HTML5的File API应用

长文一篇,分享我最近使用HTML5 File API的经验。

HTML5新增了很多特性,其中File API是非常重要的部分。在肉大师中,我大量使用了HTML5的文件API,这样一来可以给予用户近乎桌面软件的体验,二来还能减少服务器和带宽的消耗。今天终于把最后几个问题解决了,在这里总结下HTML5 File API的使用。

随着用的越来越多,发现自己其实搞混了“File API和FileSystem API”两个东西。而且类写的也有问题。等到有空的时候把这篇文章重写一下好了。(2012-09-13)

用途

在W3C页面上,列出了File API可能用到的场合(以下为意译,可能有所偏颇,欢迎对比原文阅读):

  1. 断点续传
    • 上传时,先把目标文件复制到本地沙箱,然后分解逐块上传
    • 浏览器崩溃或者网络中断也没关系,因为恢复后可以续传
  2. 需要大量媒体素材的应用,比如视频游戏
    • 下载压缩包,在本地解压,就能恢复之前目录结构
    • 跨平台
    • 通过渐进式下载,进入新关卡或者开启新功能均无需等待,因为玩的时候所需素材已经通过后台下载完成了
    • 从本地缓存中直接读取素材,速度飞快
    • 二进制文件也不在话下
    • 使用压缩包可以大大减轻带宽和服务器消耗,也避免了频繁下载碎片文件带来的检索问题
  3. 离线图片/音频编辑器通
    • 不怕频繁读写大量数据
    • 只想重写文件的某些部分也能做到(比如修改ID3或者EXIF信息)
    • 创建目录组织项目后用起来舒服多了
    • 编辑完的文件还能被iTunes、Picasa之类的本地应用访问
  4. 离线视频播放器
    • 下载超过1G的大文件,将来想看再看
    • 可以在不同时间点间来回跳转播放
    • 能够给Video标签提供URL
    • 即便片子还没下完,也能把下载到的部分先睹为快
    • 还能任意截取一段视频交给Video标签播放
  5. 离线邮件客户端
    • 下载保存附件到本地自不必说
    • 断网的情况下,可以缓存用户要上传的附件,以后再上传
    • 需要时可以列出缓存里的附件,通过缩略图显示,预览后上传
    • 能像正常服务器那样触发标准的下载动作
    • 不仅能使用XHR一次性上传全部内容,还可以把邮件和附件拆解成小块依次发送

听起来都是些令人振奋的功能,实际用起来还是要踩点坑。下面就把我的经验分享一下。

继续阅读“HTML5的File API应用”

Windows 8 64bit,Chrome 18,display:none的<input type=”file” />无法通过JS手工触发click事件的方法来打开选择文件的窗口。添加到页面内也不行,不知道是不是所有不显示的标签都不会广播click事件,回头验证下。

Backbone.js经验两则

最近使用backbone遇到的两个问题,分享下。

使用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);

CMDN Club 16期归来

下午去参加了“CMDN Club 16期——跨平台开发框架PhoneGap入门与实践”,有一些收获,整理记录下来。

  1. 会上着重讲了Android和iOS下使用plugin扩展PhoneGap功能的方法。
    1. Android上使用prompt实现。js通过prompt发送请求,WebView侦听到prompt后,解析并进行处理。处理完之后,将返回的数据放在内建的XHR服务器上;而应用在发出请求后,就在不断轮询,得到数据后返回给预先设定的callback。
    2. 比较特殊的地方在于,Android支持同步和异步两种形式,一般推荐使用异步,这样进程就不会被锁死,用户体验得以保障。
    3. iOS版则是建立一个iframe,把请求格式化后放进iframe的src。WebView接触到特殊标记的url就会进行处理,得到返回值之后,将js交给WebView处理。因为使用了iframe,所以操作都是异步无阻塞的。
  2. PhoneGap默认提供了很多本地api的封装,不过想要达到native的标准,自己补充插件是必不可少的。
  3. PhoneGap已经捐赠给Apache基金会,以后叫Cordova,代码组织会更加规范,而且会向AMD方向发展。看来研究下Require.js也很有必要。
  4. Weinre是个调试利器,非常适合调试移动设备,不仅是PhoneGap,日常开发也会很有用。
  5. Adobe Shadow是在Weine基础上封装的一个工具,目标是同时调试多台设备,不过目前还处在实验室阶段,将来会是非常好用的产品。持续关注吧。
  6. jQuery Mobile性能不是一般差,看来很有必要研究下Sencha Touch。
  7. www.phonegap.cn是个非官方组织,今天第二位嘉宾就是它的站长,看起来很靠谱的一个人。
  8. 对于我之前提到的防盗链问题,他也没有好建议,只提出一些想法:
    1. 使用插件抓取图片,转换为base64字符串,再显示出来。没记错的话这样会有兼容性问题,而且html也会很难看。
    2. 修改PhoneGap代理所有http请求。这个难度比较大。
  9. 现在没有命令行工具,他们正在开发。希望肉大师第一版完工的时候能用上。
  10. 会上有不少非人类思维的提问者,我感觉嘉宾都很迷茫。

重写Backbone.js的加载动作

解决覆盖Backbone.Model的parse方法无效的问题。

居然在Google里找不到类似的情况,难道只有我一个人会有这种疑问么……

我在使用Backbone的时候,遇到一个问题:我需要用 Backbone.Model 或者 Backbone.Collection 来加载一些远程数据,一般来说都是静态文件,比如HTML或者XML,既不满足RESTful,也不是JSON;虽然不很符合Backbone的要求,不过因为是静态的,所以我觉得ajax应该都没问题。当我按照这个思路写下去,一般就是这样:

var MyModelClass = Backbone.Model.extend({
  url: 'config.xml',
  parse: function (response) {
    console.log(response);
  }
});
var model = new MyModelClass();
model.fetch();

但是运行之后,我发现被覆盖的 parse 没有执行。然而查看网络,目标文件已经被正常加载。作为Backbone的初学者,也不知道问题出在哪里。不得已找来源码跟踪,发现Backbone实现 fetch 是委托给 Backbone.sync 方法,但是在实现的时候会把数据格式设置为json:

// http://documentcloud.github.com/backbone/backbone.js
// Default JSON-request options.
var params = {type: type, dataType: 'json'};

而 jQuery 1.4版之后,会对返回的数据格式进行验证,如果不符合就抛出异常。所以当我那些不是 JSON 但声明是 JSON 的数据加载完毕后,jQuery 就会抛出异常,于是覆盖的parse也就不执行了。

如果远程数据不是JSON,需要覆盖数据加载逻辑时,就应该覆写 .fetch(),比如这样:

var MyModelClass = Backbone.Model.extend({
  url: 'config.xml',
  fetch: function () {
    $.ajax({
      url: this.url,
      context: this,
      success: this.parse
    });
  }
  parse: function (response) {
    console.log(response);
  }
});

var model = new MyModelClass();
model.fecth();

我认为不应该重写 .sync(),因为实际应用中,不同的 Model 和 Collection 可能要提供加载远程数据、加载模板、与 LocalStorage 交互等不同的功能,重写sync也很难满足需要。所以不妨直接在不同的类里面覆盖各自的fetch、save方法。


这篇文章还有人看,那就更新一下。(2016-11-25)

Backbone 用的久了,发现它其实设计了更好的办法解决这种问题:调用 .fetch() 的时候传递 options

// 以下代码通过继承并覆写 .fetch() 方法,告知 jQuery 返回数据类型是 XML
var MyModel = Backbone.Model.extend({
  fetch: function (options) {
    options = options || {};
    options.dataType = 'xml';
    return Backbone.Model.prototype.fetch.call(this, options);
  },
  parse: function (response) {
    console.log(response); // jQuery 会帮我们分析这个 XML
  }
});

这种方式比上面的好得多。

目前使用PhoneGap遇到的问题

使用PhoneGap至今,遇到了不少问题;将来想做的功能也有一些不太知道该怎么做的,都记在这里,作为将来要攻克的难关,也作为将来要分享的文章目录。

使用PhoneGap至今,遇到了不少问题;将来想做的功能也有一些不太知道该怎么做的,都记在这里,作为将来要攻克的难关,也作为将来要分享的文章目录。

  1. PhoneGap没有提供修改Refer的API,可能需要开发插件来实现,不知道Titanium有没有类似的功能
  2. PhoneGap没有提供后台运行service的API,这给推送信息带来了一些问题,不过似乎StackOverFlow上有人提供了解决方案,准备试试
  3. 自动升级。这个利用现有api应该可以完成。
  4. 缓存内容到本地。

总结下蜂鸟镜头库App开发

前些日子利用业余时间研究PhoneGap+jQuery Mobile开发,找这个项目练手。写到一半又拿Backbone重构了下。如今还有很多问题,先停下来总结一下。

前些日子利用业余时间研究PhoneGap+jQuery Mobile开发,找这个项目练手。写到一半又拿Backbone重构了下。如今还有很多问题,先停下来总结一下。

  1. 效率问题。屏幕越大效率越差,在Kindle Fire的表现也不如想象中理想。
  2. 启动速度慢。不像跑在浏览器那样,瞬间就打开了(因为会忽视掉打开浏览器和渲染的时间),所以应该需要一张图片作为启动图片——这个图片似乎不能自动缩放——在Kindle Fire里会导致程序崩溃。
  3. jQuery Mobile还有一些bug,目前还不确定原因和解决方案。
    1. 我有两个ul要做成listview,第一个什么都不写,填充内容后.listview()一下就可以;第二个则必须在html里就写好data-role=”listview”才行。
    2. 切换页面的时候只能从右往左,reverse=true也不行
  4. jQuery Mobile没有弹出组件,dialog的实现是跳转页面,不是很爽。
  5. Backbone是个好东西,尤其是开发过Flash,用起来感觉更顺手了。
  6. Backbone 0.9.1复写Collection的parse方法无效,不知道是为什么
    问题已解决:《重写Backbone.js的加载动作》
  7. 当需要事件从一处发生,而在另一处响应的时候,Backbone并没有提供很好的办法,用惯了robotlegs之类的框架在这里略有不爽。我想拿Model来作为Mediator应该不错。

再练手的话,准备用去哪儿的api,感觉挺开放的。

使用PhoneGap+jQuery Moblie开发蜂鸟镜头库手机App

拿以前做蜂鸟镜头库的两个接口尝试开发蜂鸟镜头库app,基本完工。这里总结下踩过的坑。

蜂鸟镜头库app效果图
蜂鸟镜头库app

自从春节期间在家尝试了PhoneGap之后,一直想做点实际的东西,好总结点经验,以备不时之需。可惜后台苦手,数据源是个问题。后来想起来以前做蜂鸟镜头库的时候有两个接口,可以取得完整的数据,于是便动起手来,开始做这个app。

开发本身并不复杂,大概花了一天时间搞出雏形,加上翻页基本就能发布了。不过还是遇到不少问题,今天简单总结下踩过的坑,以免以后再踩。
继续阅读“使用PhoneGap+jQuery Moblie开发蜂鸟镜头库手机App”