去年做雪球的timeline模块时我正深受 #newTwitter 的影响,倾向于把尽可能多的逻辑放到客户端去做,最后实现的时候选择了Backbone.js。使用Backbone.js的好处就不说了,这一两年它火的一塌糊涂,到处都是介绍的文章,而且这篇文章的重点也不是这个。

下面我假设您已经了解Backbone.js的作用和实现方式。

在页面初始化的时候,与发起一个ajax请求去取初始数据相比,把初始数据输出到页面里是一个更好的方案。Backbone.js提供了一个Loading Bootstrapped Models的FAQ,雪球也正是这样做的。把初始数据的json输出到页面里,然后Backbone.js用这个json来渲染页面。

但是这一年的实践中陆续发现一些问题:接口输出的timeline json里某些字段里偶尔出现一些不可见的换行符,导致浏览器解析json的时候出错。输出json字符串有injection可能(后来今年三月份的时候backbone特意在文档里加上了提示)。另外,随着业务复杂性的增长,接口直接输出的json体积在膨胀,很多属性已经不是页面展示所必须的,json的体积已经接近甚至已经超过了生成的html的体积。

同时我还在思考另外一个问题,backbone的使用场景其实是app,DocumentCloud、Trello这种需要反复对页面元素操作,应用要处理好数据和UI的一致性,初始化的时候稍微慢一点也没有关系,用backbone再好不过了。但是雪球其实更像是page,用户打开页面希望尽早的看到数据,当然我们也需要经常操作页面的元素,也需要处理数据和UI的一致性问题。

在服务端把html就拼好然后传给浏览器似乎是最直接的答案。那么接下来就面临了这篇文章要处理的问题了,如果既用服务端渲染html,又能够继续使用现有的基于backbone的客户端程序,甚至可以随时切换渲染位置。

backbone的文档似乎没有明确的给出这样的建议,但是稍微思考一下backbone View的实现方式应该可以想到,既然view的events是绑在一个根el上面的,那么这个el是一个空的wrapper或者已经渲染好的html片段并不影响事件的delegate。

var TimelineView = Backbone.View.extend({events: {"click .comment": "comment"}.comment: function(e){var $elm = $(e.target), statusModel = this.collection.get($elm.data("id"))renderComment(statusModel)},render: function(){var timelineHtml = ''// some code to generate html from models$(this.el).html(timelineHtml)}})var statusCollection = new StatusCollection(statusList)var timelineView = new TimelineView({el: $("#timeline"),collection: statusCollection})timelineView.render()

假设上面的一段代码是已有的客户端渲染的实现方式,需要说明的是statusList正是我们之前输出到页面里的timeline json,$("#timeline")是准备放timeline的wrapper。

现在改成服务端渲染之后发生的变化的后果,$("#timeline")变成了已经塞满status的列表,statusList不再存在。我们挨个解决。

$("#timeline")既然已经填满了,就不用再render啦。最后一行就改成了:

if ($("#timeline").html().trim()){timelineView.render()}

statusList是空的,那么statusCollection也是空的,comment的时候就找不到status的model。本来作为json输出来的数据其实被塞到了dom里,那我们就应该找一个合适的时候把status model从dom里读出来。我选择在view初始化的时候获取,给TimelineView加上initialize方法。

var TimelineView = Backbone.View.extend({initialize: function(){if (this.collection.length) {var models = []// some code to read models from timeline domthis.collection.add(models)}},...})

好了,客户端的代码没有任何其他要改的了,所有的backbone的功能都会跟原来一样的工作,还可以吧?

最后完整的代码改造成了这样:

var TimelineView = Backbone.View.extend({initialize: function(){if (this.collection.length) {var models = []// some code to read models from timeline domthis.collection.add(models)}},events: {"click .comment": "comment"}.comment: function(e){var $elm = $(e.target), statusModel = this.collection.get($elm.data("id"))renderComment(statusModel)},render: function(){var timelineHtml = ''// some code to generate html from models$(this.el).html(timelineHtml)}})var statusCollection = new StatusCollection(statusList)var timelineView = new TimelineView({el: $("#timeline"),collection: statusCollection})if ($("#timeline").html().trim()){timelineView.render()}

后记

这种处理对于需要SEO,或者特殊设备支持的应用来说更有意义。

服务端渲染html会给服务端带来额外的cpu消耗,但是很小。不过我们还是做了适配,可以随时切换渲染方式。

服务端渲染也需要模板,客户端渲染也需要模板,这个模板如何复用?对于使用node.js的雪球来说,很好处理。这个留给以后说。

backbone 模板 html,用Backbone.js绑住服务端生成的html相关推荐

  1. Pomelo:网易开源基于 Node.js 的游戏服务端框架

    Pomelo 是基于 Node.js 的高性能.分布式游戏服务器框架.它包括基础的开发框架和相关的扩展组件(库和工具包),可以帮助你省去游戏开发枯燥中的重复劳动和底层逻辑的开发.Pomelo 不但适用 ...

  2. nuxt.js之SSR服务端内存泄漏导致CPU过高的解决过程

    问题 最近在公司维护nuxt项目时,线上遇到了一个问题--访问网站,网站会报502或者JS.css资源报502. 去运维那一查pm2,项目node服务器的CPU达到了100%,实际上这段时间并没有人访 ...

  3. js与C#服务端 json数据交互

    1.1 服务端返回给前端 返回的数据都放入对象中(根据需求:单个对象,集合,键值对),然后JSON序列化返回给前端.这里可以引用JSON.NET 库,也可以用.NET自带的类库: JavaScript ...

  4. 用 next.js 做一个服务端渲染的加密货币网站

    学习 next.js next.js 是一个基于 React 的通用 JavaScript 框架,next.js 为 React 组件模型提供了扩展,支持基于服务器的组件渲染 (SSR),同时也支持在 ...

  5. 17 SSR:使用 React.js 开发 Serverless 服务端渲染应用

    今天我想和你聊一聊怎么用 Serverless 开发一个服务端渲染(SSR)应用. 对前端工程师来说,Serverless 最大的应用场景之一就是开发服务端渲染(SSR)应用.因为传统的服务端渲染应用 ...

  6. Nuxt.js 开发SSR(服务端渲染)Web应用

    1. 初识 Nuxt.js Nuxt.js 是一个基于 Vue.js 的通用应用框架. 与 vuepress 的关系: Nuxt.js 能够胜任 VuePress 的功能,但它专为构建应用程序而设计, ...

  7. 让 ASP.NET JS验证和服务端的 双验证 更简单

    转自: http://www.cnblogs.com/sunkaixuan/p/4550580.html 只用JavaScript验证安全不安全谁都知道,答案是不安全,非常的不安全.因为在客户端进行的 ...

  8. nuxt.js实战asyncdata服务端渲染

    Nuxt扩展了Vue的生命周期: export default {middleware () {}, //服务端,中间件validate () {}, // 服务端asyncData () {}, / ...

  9. 阿里云OSS服务端签名前端JS直传(php)示例

    阿里云OSS服务端签名后前端JS直传(php)示例 需求:服务端上传图片太慢,需要使用前端直传的方式.但前端把阿里云的 AccessKey ID 和 AccessKey Secret 放在前端文件中会 ...

最新文章

  1. LinearAlgebra_1
  2. python 装饰器 参数-python装饰器参数那些事_接受参数的装饰器
  3. 15.Three Sum
  4. 用径向函数和球谐函数计算氢原子能级并验证维里定理
  5. 第一次连接mysql失败_MySQL 远程连接失败
  6. 移植驱动完毕后加载时的version magic报错原因以及解决办法
  7. 图解Transformer-一篇文章看懂transformer
  8. 华尔街顶级大师胡立阳名言
  9. 26期20180718 rsync
  10. 安装rarlinux及问题解决
  11. 如何按行政区划下载谷歌卫星地图并裁剪
  12. 【车牌识别】基于模板匹配算法实现国外车牌识别附matlab源码
  13. 转载:Max vs Maya
  14. nginx的access.log文件详解
  15. 从三个层面来谈下自己的团队管理心得及感悟
  16. 腾讯视频格式如何转换成mp4 将下载的qlv文件转换成mp4的方法
  17. jupyter notebook如何显示行号?
  18. Markdown表格、单元格合并、快速编辑表格
  19. docker安装wnameless/oracle-xe-11g并运行(手写超详细)
  20. 英语单词记忆以及句式记忆

热门文章

  1. Java窗体小游戏开发飞机大作战Java小游戏开发源码
  2. MFC播放MP3格式音乐
  3. 消息推送分类:通知和透传
  4. Sql的with as 的使用
  5. 单商户商城系统功能拆解41—应用中心—用户储值
  6. guava中的Table
  7. Guava入门~CacheStats
  8. 小红书运营模式和思路解析,新手账号运营实操必看
  9. 第10章:深入浅出Ansible
  10. 毕业设计之 - 大数据分析:电商产品评论数据情感分析