来纠结一下异步web支持浏览器前进后退吧

2012-05-03 13:25:42 +08:00
 aligo
最近两周开始想做一个比较酷的东西,想在各个方面做得比较高大全什么的,然后想要比较酷又好维护,响应式设计啊+尽可能的异步+合适动态效果啊+各种洁癖等等。

问题1:
大家平时会经常用到浏览器的前进后退吗?
》关于前进后退这个问题几乎不会被注意到,在没有ajax的时代的浏览器前进后退是不用特意去支持的事情,所以几乎成了不被注意到细节问题。只不过我想应该还有很大一部分用户会去用这个功能吧?特别是考虑到通过响应式设计的方式去支持移动设备,现在android设备都有一个用来后退的独立按键。但是例如像XX微博web手机版(OO微博我没试过)的异步,居然是不支持后退的,一按返回键不会回到上一屏而是跳到别的地方去了。

问题2:
你会怎么处理异步发起http请求的前进后退?
》最常见的做法是通过改变hashbang或者pushState的方式去使浏览器记录下状态的改变(下简称pushState),然后浏览器再回调到对应的绑定事件上,然后发起xhr请求,并且渲染结果。这方面的例子就是jquery.pjax了。这样的有一个问题就是每次后退前进,都会造成网络请求。另外还有一个问题,就是所有的xhr请求事实上都从一个地方发起,如果根据不同的请求内容想要加入不同的动态效果,代码会集中在一起,没办法根据不同页面分开管理。

》然后我自己在去年这个时候做法,类似于上面那种反过来的方式:在发起xhr请求的同时,向浏览器pushState,同时把xhr的success闭包对象存入到一个Stack里。日后在前进后退时,回调函数就去执行一次对应的success,因为success把xhr的结果都缓存起来了,所以不会有多余的请求(虽然没办法得到最新的数据,但是后退的话不一定想到最新数据不是吗?)。同时可从不同的地方发起请求,并且在success按照自然习惯的使用方式加入各种扩展功能。我去年做的东西(jquery.barca)在http://vivo-dev.aligo.me/ (应该还能用吧)。但是现在觉得这种其实也不太好。

》然后是各种js mvc框架。其实它们的做法和第一种方法有点像,只不过在浏览器状态变更地方加入了router,然后把代码分散到mvc结构里,方便管理(不过最后我还是得把它们打包到一个文件里并且要求客户端缓存的)。同时在model层也可以做暂时的数据缓存不请求。因为我是一个人包办前端后端,后端上一直会采用restful的规划方式,所以js mvc其实是挺适合我的胃口的。只不过为了bot抓取,或者不支持js的用户访问(洁癖原因我一直坚持例如链接的地方href照写再单独绑定click事件)。当然用了前端mvc框架确实也可以做到这个,只不过例如模版之类的东西,前后端得做两份了。所以一直感觉js mvc比较适合像evernote那样单屏界面的东西,不太适合做比较多内容模式的东西。(主要还是工程量和是否容易维护的问题)

》所以目前我也没想到太好的方式。感觉还是差点什么东西-A-

问题3:
大家觉得这方面做得比较好的是?
》我自己觉得例如gmail用起来挺舒服的,采用方式1,只不过一看代码,全部inline的js啊css,一大坨东西,而且gmail也算是只有单屏界面。然后中间数据是一种类似S-表达式的奇怪东西,google的geek都是怪物吗?我有洁癖觉得这样的东西不好也难以维护。

》然后考虑到要响应式设计啊之类时髦的东西啊同时尽可能地好维护我就。。。
4179 次点击
所在节点    问与答
9 条回复
spritevan
2012-05-03 13:38:14 +08:00
backbone 就好, 不纠结 SEO
reorx
2012-05-03 15:30:22 +08:00
我自己只用过Backbone,所以说一下Backbone的处理方式,你来看看合不合适。

首先有一点要说到的是,如果客户端要做得高大全,在代码中使用到某一种模式和理念几乎是必然的事情了。记得以前只会用jQuery的时候,经常做的事情就是要在一个效果结束后动态地给它所生成或影响到的元素绑定或解绑事件,有时一个ajax要包好几层回调函数,代码会一片混乱,痛苦地不行。于是开始意识到框架的好处。有时会觉得框架有所限制,但它更好地是给你提供了一个可参考的整体解决方案,因为是前人智慧的结晶,总好过自己从头摸索。若真有一天觉得它不能满足需求了,自己也可以整合自己学到的东西来造一个新的轮子。

那么就是框架的选择问题了。一般的js框架都是应用了一种或几种设计模式的。对于这些知识我了解的比较少,由于以前作Django开发的时候接触过MVC的概念,又更喜欢OOP的编程模式,便挑选了Backbone。

Backbone有两个特点,一是让你尽可能地将数据处理和逻辑分离开,写Model的时候不要考虑View的存在,反之亦然。二是提倡尽量将函数写在一个类中。即便一个View在整个网站中只可能存在一个实例,也要写在类中将它实例化出来。

对于ajax和history的处理,在Router的控制下,页面的前进后退不会发出新的请求。具体的实现方式我没有看太多它的代码,想来基本能满足你的需求。

事件绑定的方式非常地赞,可以直接用jQuery选择器映射到类中的某个方法。

模板我觉得应该不是问题,一般在页面上加载一份然后用jQuery来拿就可以了,为什么需要做两份呢。

总得来说,虽然你写的问题很纠结,我也似乎没有作针对性的回答,但对clipcan的直觉告诉我你应该使用一个MVC框架。当然,以上说的都仅作参考,js我非常业余,Backbone也只写过一个项目,不过我觉得人总是得做一步看一步嘛,不可能一开始就考虑全所有的问题,也不可能有一个完美的解决方案,先上再说 :)
aligo
2012-05-03 15:37:44 +08:00
js mvc框架是很好,可是view都是写在前端了,爬虫什么的爬不了,而且后端能做的一些fancy的东西挪到前端来也不行了
模版的话倒是有想过给后端模版输入一个dummy对象,用来生成mustache式的前端模版
然后没了,主要还是爬虫的问题囧
airyland
2012-05-03 15:44:56 +08:00
@aligo @spritevan 关于SEO, 搜索引擎可以提交sitemap文件,如果要再酷的话,就用google 的#!方式。
aligo
2012-05-03 15:49:52 +08:00
@airyland 我一直在让程序自己ping sitemap,只不过如果只做backbone的话,无论是hashbang还是history api,爬虫是抓取不到任何东西的啊
除非是爬虫支持dom和js。。。
reorx
2012-05-03 15:51:54 +08:00
@aligo 唉我明白了,这个问题确实难以解决囧囧囧

@airyland `#!`只是说,google的爬虫会去抓取这种格式的url,但如果这个url的内容是通过js在浏览器上渲染的,爬虫可能就无法抓到我们想让它看到的东西了。
airyland
2012-05-03 16:06:02 +08:00
@reorx @aligo 对的,上面没说清楚,爬虫没那么高级,所以需要至少写个简单的页面做静态输出。
www.example.com/ajax.html#!key=value
对应于
www.example.com/ajax.html?_escaped_fragment_=key=value
aligo
2012-05-03 16:30:38 +08:00
@airyland 恩,就是这样。例如我在http://vivo-dev.aligo.me/中实现的,如果直接点下去就是异步的效果,并且地址会变成http://vivo-dev.aligo.me/planets/0000/topics/3f3229ef或者低级浏览器里hashbang的形式,而单独打开访问就是纯静态。包括编辑回复之类的地方也是如此
但是这是一个简单的论坛程序,目前在做的是一个稍微复杂点,而且不是单一屏幕模式的东西,如果这么在做觉得不太好维护。

总之想做一个比较酷的感觉,这两周在各种各样的方向乱开科技树。。。
qiukun
2012-05-03 18:02:51 +08:00
听说 gmail 是将前后两屏存起来 @gxx

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/34474

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX