JavaScript宝座:七大框架论剑

openkk 12年前
   <div id="news_body">     <p>        英文原文:<a href="/misc/goto?guid=4958521772149889670" rel="nofollow" target="_blank">Rich JavaScript Applications – the Seven Frameworks</a>    </p>     <p>        一周前,<a href="/misc/goto?guid=4958521772248730511" rel="nofollow" target="_blank">Throne of JS 大会</a>在多伦多召开,这应该是我参加过的最有料也最不一样的一次大会。大会官网如是说:</p>     <blockquote>      <p>加载整个页面,然后再“渐进增强”以添加动态行为,这种构建 Web 应用的方式已经不够好了。要想让应用加载快,反应灵敏,而且又引领潮流,必须彻底检讨你的开发手段。</p>     </blockquote>     <p>        这次大会邀请了七大 JavaScript 框架/库的创建人,他们济济一堂,面对面交流各自的技术理念。所谓七大框架/库分别是:AngularJS、Backbone、Batman、CanJS、Ember、Meteor、Knockout、Spine。<sup><a href="/misc/goto?guid=4958521772149889670" rel="nofollow" target="_blank">1</a></sup></p>     <p>        <strong>声明:</strong>我在会上讲 Knockout,因此我的观点显然不是中立的。在这篇文章中,我重点讨论这些创建人的思路和技术理念,尽量不提我赞成或反对什么。</p>     <p><em>        <sup><a href="/misc/goto?guid=4958521772149889670" rel="nofollow" target="_blank">1</a></sup> 没错,是 8 个框架,不是 7 个。但到底怎么回事儿,会议主办方也没有明确给我们解释过……</em></p>     <p style="text-align:center;"><a title="JavaScript 宝座:七大框架论剑" rel="lightbox[24878]"><img title="JavaScript 宝座:七大框架论剑" alt="JavaScript宝座:七大框架论剑" src="https://simg.open-open.com/show/f85999b8b86df405dbc0c1eb5a940cf1.jpg" width="541" height="294" /></a></p>     <p>        <strong>文章可长啦,先概述一下:</strong></p>     <ul>      <li>对许多 Web 开发人员来说,要构建富 Web 应用,使用客户端框架是理所当然的。如果你什么框架也没用,那要么你不是在做应用,要么就会错过很多好东西。</li>      <li>在使用方法上,这些框架很多地方都是一致的(模型-视图-*架构、声明绑定,等等——详见下文) ,因此从某种意义讲,无论你选择哪一个,都能得到同样的好处。</li>      <li>理念上还是有不少差异,特别是在对框架和库的看法上,分歧格外大。你的选择会深刻影响你的架构。</li>      <li>会议本身活泼,新颖,技术小组之间有很多交流和对话。我希望能有更多类似的会议。</li>     </ul>     <p>        <strong>技术:共识与分歧</strong></p>     <p>        随着每个 SPA(Single Page Application,单页应用)技术的逐一展示,一些相当明显的相似性和差异性浮出了水面。</p>     <p>        <strong>共识:渐进增强不能建立真正的应用</strong></p>     <p>        各技术门派一致认为,真正的 JavaScript 应用必须有适当的数据模型,并具备客户端渲染能力,而绝不仅仅是服务器处理数据再加上一些 Ajax 和 jQuery 代码那么简单。</p>     <p>        用 Backbone 创建人 Jeremy Ashkenas 的话说:“现如今,你说‘单页应用’,都跟说‘不用马拉的车’差不多了”(意思是,早已经没那么新鲜了)<sup><a href="/misc/goto?guid=4958521772359664610" rel="nofollow" target="_blank">2</a></sup>。</p>     <p>        <sup><a href="/misc/goto?guid=4958521772359664610" rel="nofollow" target="_blank">2</a></sup> <em>“不用马拉的车”(horseless carriage)是汽车刚刚发明的时候,人们对它的称呼。——译者注</em></p>     <p>        <strong>共识:模型-视图-某某</strong></p>     <p>        所有技术门派都坚持模型-视图分离。有的强调 MVC(Model View Control),有的提到 MVVM(Model View ViewModel),甚至有人拒绝明确说出第三个词儿(只提模型、视图,然后加上让它们协调运作的东西)。对各门派而言,最终结果其实是相似的。</p>     <p>        <strong>共识:推崇数据绑定</strong></p>     <p>        除了 Backbone 和 Spine 之外,其他框架都在自己的视图里内置了声明数据绑定的机制(Backbone 的设计理念强调让用户“自选视图技术”)。</p>     <p>        <strong>共识:IE6已死</strong></p>     <p>        在小组讨论中,大多数框架的创建者说,他们对 IE 浏览器的支持只限于7+(事实上,Ember 和 AngularJS 的起点是 IE8,Batman 需要 ES5“垫片”才能在 IE9 之前的 IE 版本中使用)。这也是大势所趋:<a href="/misc/goto?guid=4958346310812879113" rel="nofollow" target="_blank">jQuery 2 已经不打算支持 IE9 以下的旧版本 IE 了</a>。</p>     <p>        只有 Backbone 和 Knockout 还坚定支持 IE6+(我不清楚 Backbone 的内部实现,但 Knockout 会把 IE6/7那些令人抓狂的渲染及事件方面的怪异行为屏蔽掉)。</p>     <p>        <strong>共识:许可和源代码控制</strong></p>     <p>        大家都使用 MIT 许可,并且托管在 GitHub 上。</p>     <p>        <strong>分歧:库与框架</strong></p>     <p>        这是目前最大的分歧。下表对 JavaScript 库和框架进行了归类:</p>     <table class="ke-zeroborder">      <tbody>       <tr>        <td>JavaScript 库</td>        <td>JavaScript 框架</td>       </tr>       <tr>        <td>Backbone(9552)</td>        <td>Ember(3993)</td>       </tr>       <tr>        <td>Knockout(2357)</td>        <td>AngularJS(2925)</td>       </tr>       <tr>        <td>Spine(2017)</td>        <td>Batman(958)</td>       </tr>       <tr>        <td>CanJS(321)</td>        <td>Meteor(4172)——了不起,见下文</td>       </tr>      </tbody>     </table>     <p>        <em>*括号中的数字是最近某个时间点 GitHub 上的关注者数量,粗略地代表各自的<a title="影响力" href="http://www.amazon.cn/gp/product/B0044KME2E/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&tag=vastwork-23&linkCode=as2&camp=536&creative=3200&creativeASIN=B0044KME2E" rel="nofollow" target="_blank">影响力</a>。</em></p>     <p>        <strong>什么意思呢?</strong></p>     <ul>      <li><strong>JavaScript 库</strong>,插到既有架构中,补充特定功能。</li>      <li><strong>JavaScript 框架</strong>,提供一个架构(文件结构啊,等等),你必须遵守它,只要你遵守,那剩下的就全都是处理通用需求了。</li>     </ul>     <p>        目前来看,鼓吹框架模型最卖力气的是 Ember,其创建人 Yehuda Katz 之前是(理念相似的)Rails 和 SproutCore 项目的开发者。他的观点是,缺少任何组件都不够给力,都不能说是真正在推动技术进步。相反的观点说,库的目的更明确,因而更容易掌握、采用、定制,也有助 于把项目风险降到最低,毕竟你的架构不会严重依赖任何一个外部项目。根据我参加对话的情况看,现场观众也分成了两派,有支持框架的,也有支持库的。</p>     <p>        请注意,AngularJS 可以说是介于库和框架之间一种形态:它不要求开发时遵守特定的文件组织方式(与库类似),但在运行时,它提供一个“应用生命周期”,可以对号入座地把代码 安排进去(与框架类似)。之所以把它归入框架之列,是因为 AngularJS 团队乐于接受这个说法。</p>     <p>        <strong>分歧:灵活,还是整合</strong></p>     <p>        每个技术门派都有不同程度的强制性规定:</p>     <table class="ke-zeroborder">      <tbody>       <tr>        <th> </th>        <th>视图</th>        <th>URL 路由</th>        <th>数据存储</th>       </tr>       <tr>        <td>AngularJS</td>        <td>内置基于 DOM 的模板(强制)</td>        <td>内置(可选)</td>        <td>内置系统(可选)</td>       </tr>       <tr>        <td>Backbone</td>        <td>自选(最常用的是基于字符串的模板库 handlebars.js)</td>        <td>内置(可选)</td>        <td>内置(可重写)</td>       </tr>       <tr>        <td>Batman</td>        <td>内置基于 DOM 的模板(强制)</td>        <td>内置(强制)</td>        <td>内置系统(强制)</td>       </tr>       <tr>        <td>CanJS</td>        <td>内置基于字符串的模板(强制)</td>        <td>内置(可选)</td>        <td>内置(可选)</td>       </tr>       <tr>        <td>Ember</td>        <td>内置基于字符串的模板(强制)</td>        <td>内置(强制)</td>        <td>内置(可重写)</td>       </tr>       <tr>        <td>Knockout</td>        <td>内置基于 DOM 的模板(可选,也可以用基于字符串的模板)</td>        <td>自选(大都使用 sammy.js 或 history.js)</td>        <td>自选(如 knockout.mapping 或只用$.ajax)</td>       </tr>       <tr>        <td>Meteor</td>        <td>内置基于字符串的模板(强制)</td>        <td>内置(强制?不确定)</td>        <td>内置(Mongo,强制)</td>       </tr>       <tr>        <td>Spine</td>        <td>自选基于字符串的模板</td>        <td>内置(可选)</td>        <td>内置(可选?不确定)</td>       </tr>      </tbody>     </table>     <p>        不难想见,只要某个库在某方面是开放的,他们的人就会强调只有这样才能从总体上确保跟第三方库兼容。同样,显而易见的反对意见则是,只有内置才 能保证无缝整合。再次,根据我参加的对话,现场观众也各持己见,说什么的都有,基本上可以看出每个人对其他技术组合的了解程度。</p>     <p>        Ember 的 Tom Dale 说:“我们加入了很多魔法,但都是有用的魔法,换句话说,它们可以分解为常规的操作原语。”</p>     <p>        <strong>分歧:基于字符串的模板与基于 DOM 的模板</strong></p>     <p>        (请参考上面的表格。)对基于字符串的模板,大家几乎都选择 Handlebars.js 作为模板引擎,它俨然成了这个领域的霸主,当然 CanJS 用的是 EJS。对基于字符串的模板,支持的人认为“它更快”(不一定),而且“理论上,服务器也可以处理它”(也不一定,因为前提必须是在服务器上运行所有模型 代码,而实践中根本没人那么做)。</p>     <p>        而基于 DOM 的模板呢,意味着纯粹通过在实际标记中绑定来控制流程(each、if,等等),且不依赖任何外部模板库。支持的声音有“它更快”(不一定),另外“代码易读、易写,且标记与模板之间没有隔阂,CSS 如何与之交互也一目了然。”</p>     <p>        在我看来,最有吸引力的说法来自 AngularJS 那帮家伙,他们认为在不久的将来,基于 DOM 的模板会得到浏览器原生支持。所以我们最好现在就用,从而可以轻松应对未来。AngularJS 来自 Google,所以他们在开发 Chromium 时会考虑这一点,而且也会说服标准主体接纳这个建议。</p>     <p>        <strong>分歧:服务器中立到什么程度</strong></p>     <p>        Batman 和 Meteor 明显依赖服务器:Batman 是为 Rails 设计的,而 Meteor 本身就是服务器。其他大多数都追求服务器中立。但实际上,Ember 的架构、强制性规定,以及某些工具都倾向于 Rails 开发者。当然,Ember 绝对也能跟其他服务器技术搭配,只不过眼下还需要较多手工配置。</p>     <p>        <strong>技术门派概览</strong></p>     <p>        以下是所有 JavaScript 库/框架的基本技术细节。</p>     <p>        <strong>Backbone</strong></p>     <ul>      <li><strong>Who: </strong>Jeremy Ashkenas 和 DocumentCloud。</li>      <li><strong>What: </strong></li>     </ul>     <p>        + 用 JavaScript 实现模型-视图,MIT 许可。</p>     <p>        + 只有一个文件,1000行代码,在所有库中最小!</p>     <p>        + 功能极其专一,只提供 REST 可持久模型及简单路由和回调(以便你知道何时渲染视图,但视图渲染机制由你自己选择)。</p>     <p>        + 名气最大,很多大牌站点都在用(也许是因为它最小,容易部署)。</p>     <ul>      <li><strong>Why:</strong></li>     </ul>     <p>        + 非常小,使用它之前,你完全可以通读并理解它的源代码。</p>     <p>        + 不会影响你的服务器架构或文件组织方式。可以在页面的某一部分内运行——不需要控制整个页面。</p>     <p>        + Jeremy 好像进入了一种禅宗所谓的入定的状态,对一切都能坦然接受。他就像一个大人,看着一群孩子在那里辩论。</p>     <ul>      <li><strong>Where:</strong> <a href="/misc/goto?guid=4958521772531401419" rel="nofollow" target="_blank">GitHub</a> 及 <a href="/misc/goto?guid=4958521772625141054" rel="nofollow" target="_blank">自有站点</a>。</li>      <li><strong>When:</strong> 至今已诞生近两年了。</li>     </ul>     <p>        <strong>Meteor</strong></p>     <ul>      <li><strong>Who:</strong> <a href="/misc/goto?guid=4958521772713747668" rel="nofollow" target="_blank">Meteor 开发团队</a>(他们<a href="/misc/goto?guid=4958521772805995459" rel="nofollow" target="_blank">刚募集到 1120 万美元投资</a>,因此可以全职开发)。</li>      <li><strong>What:</strong></li>     </ul>     <p>        + 前瞻性极强的一个框架,想不出有谁那么激进过(也许 <a href="/misc/goto?guid=4958521772897604825" rel="nofollow" target="_blank">Derby</a> 算一个)。</p>     <p>        + 将一个服务器端运行时环境(用 Node+Mongo 搭建)和一个客户端运行时环境衔接起来,让你的代码在两端都能运行,还包含数据库。利用 WebSockets 实现所有客户端和服务器之间的同步。</p>     <p>        + 在修改代码时就“实时部署”——客户端运行时可以即时更新而不丢失状态。</p>     <p>        + 可以<a href="/misc/goto?guid=4958521772994150198" rel="nofollow" target="_blank">看看这个视频</a>,对它的认识就会更全面。</p>     <p>        + 跟会上与我有过交流的所有人一样,我也衷心希望这个框架获得成功——Web 开发就需要这种激进的改革才能真正进步。</p>     <ul>      <li><strong>Why:</strong> 你实在觉得做常规 Web 开发太无聊了,想找点刺激。</li>      <li><strong>Where:</strong> <a href="/misc/goto?guid=4958521773088346219" rel="nofollow" target="_blank">GitHub</a> 和 <a href="/misc/goto?guid=4958521773177944515" rel="nofollow" target="_blank">自有站点</a>。</li>      <li><strong>When:</strong> 诞生时间不长;除了其核心团队在用,不知道还有没有其他站点实际在用 Meteor。不过,这个团队真是在严肃地做着一件前无古人的事。</li>     </ul>     <p>        <strong>Ember</strong></p>     <ul>      <li><strong>Who:</strong> Yehuda Katz (之前开发过 jQuery 和 Rails)、Ember 团队和 Yehuda 的公司 <a href="/misc/goto?guid=4958521773271968469" rel="nofollow" target="_blank">Tilde</a>。</li>      <li><strong>What:</strong></li>     </ul>     <p>        + 构建“超级 Web 应用”所需的一切,MIT 许可。</p>     <p>        + 功能最多,体积最大。</p>     <p>        + 融入了很多设计理念,涉及如何分解并对页面进行层次控制,以及如何利用一个状态机驱动的系统联结各个层次。</p>     <p>        + 正在开发一个功能非常完善的数据访问库(Ember.Data)。</p>     <p>        + 要在运行时控制整个页面,因此不适合开发大页面上的“富应用区”。</p>     <p>        + 对文件、URL 等都有相当严格的一套约束,不过要是不喜欢,你可以重写,只要你知道怎么做就 OK。</p>     <p>        + 设计灵感来自 Rails 和 Cocoa。</p>     <p>        + 工具:为 Rails 提供项目模板(但如果你手工编写代码,也可以使用其他服务器端平台)。</p>     <ul>      <li><strong>Why:</strong> 常见的问题应该有通用的解决方案——Ember 提供了所有通用解决方案。</li>      <li><strong>Where:</strong> <a href="/misc/goto?guid=4958521773353417687" rel="nofollow" target="_blank">GitHub</a> 和 <a href="/misc/goto?guid=4958340976610047764" rel="nofollow" target="_blank">自有站点</a>。</li>      <li><strong>When:</strong> 尚未发布1.0版,但也快了。然后,API 基本就能稳定下来。</li>      <li><strong>AngularJS</strong></li>      <li><strong>Who:</strong> Google(他们内部在使用)。</li>      <li><strong>What:</strong></li>     </ul>     <p>        + 用 JavaScript 实现模型-视图-其他,MIT 许可。</p>     <p>        + 基于 DOM 的模板,具备可观察能力、声明绑定机制,还有准 MVVM 式的代码风格(他们自己说是 Model-View-Whatever)</p>     <p>        + 内置基本 URL 路由和数据持久化能力</p>     <p>        + 工具:附带一个 Chrome 调试器插件,让你在调试的时候能够查看模型;还附带一个 Jasmine 测试框架。</p>     <ul>      <li><strong>Why:</strong></li>     </ul>     <p>        + 从概念上讲,他们说这个框架相当于一个“填料层”,盖在当前浏览器上,以实现未来的浏览器将可能原生具备的能力(即声明绑定和可观察能力)。因此,我们现在就应该着手这么来写代码了。</p>     <p>        + 对服务器架构或文件组织方式没有影响。可以用在页面的某一小部分中——不需要控制整个页面。</p>     <ul>      <li><strong>Where:</strong> <a href="/misc/goto?guid=4958521773481128726" rel="nofollow" target="_blank">GitHub</a> 和 <a href="/misc/goto?guid=4958319784807616451" rel="nofollow" target="_blank">自有站点</a>。</li>      <li><strong>When:</strong> 成品级框架,Google 已经搞出来有一段时间了。</li>     </ul>     <p>        <strong>Knockout</strong></p>     <ul>      <li><strong>Who:</strong> Knockout 团队和社区(核心团队目前有三个人,包括我)。</li>      <li><strong>What:</strong></li>     </ul>     <p>        + 用 JavaScript 实现模型-视图-视图模型(MVVM,Model-View-ViewModel),MIT 许可。</p>     <p>        + 功能集中在富用户界面元素:基于 DOM 的声明绑定模板,可观察的模型加自动依赖检测。</p>     <p>        + 没有限定 URL 路由或数据访问——可组合任意第三方库(例如,用 Sammy.js 做路由,用纯 Ajax 实现存储)。</p>     <p>        + 在降低使用门槛方面下了很大工夫,提供详尽的文档和<a href="/misc/goto?guid=4958521773605820911" rel="nofollow" target="_blank">交互式示例</a>。</p>     <ul>      <li><strong>Why:</strong></li>     </ul>     <p>        + 只做好一件事(UI),向后兼容到 IE6。</p>     <p>        + 对服务器架构或文件组织方式没有影响。可以用在页面的某一小部分中——不需要控制整个页面。</p>     <ul>      <li><strong>Where:</strong> <a href="/misc/goto?guid=4958521773699443026" rel="nofollow" target="_blank">GitHub</a> 和 <a href="/misc/goto?guid=4958330844784985666" rel="nofollow" target="_blank">自有站点</a>。</li>      <li><strong>When:</strong> 到现在已经正式发布近两年了。</li>     </ul>     <p>        <strong>Spine</strong></p>     <ul>      <li><strong>Who:</strong> Alex MacCaw。</li>      <li><strong>What:</strong></li>     </ul>     <p>        + 用 JavaScript 实现 MVC,MIT 许可证。</p>     <p>        + 由最早为O’Reilly 一本书写的示例代码发展而来,已成为一个 OSS(Open Source Software,开源软件)项目。</p>     <p>        + 是 Backbone 的一个衍生版(看名字就知道<sup><a href="/misc/goto?guid=4958521773811383886" rel="nofollow" target="_blank">3</a></sup>)。</p>     <ul>      <li><strong>Why:</strong> 你喜欢 Backbone,但又想要点<a href="/misc/goto?guid=4958521773910742439" rel="nofollow" target="_blank">不一样的东西</a>。</li>      <li><strong>Where:</strong> <a href="/misc/goto?guid=4958521773995834180" rel="nofollow" target="_blank">GitHub</a> 和 <a href="/misc/goto?guid=4958318094523520882" rel="nofollow" target="_blank">自有站点</a></li>      <li><strong>When:</strong> v1.0.0已经发布。</li>     </ul>     <p>        <sup><a href="/misc/goto?guid=4958521773811383886" rel="nofollow" target="_blank">3</a></sup> <em>Backbone 和 Spine 都是“脊椎”的意思。——译者注</em></p>     <p>        <strong>Batman</strong></p>     <ul>      <li><strong>Who:</strong> <a href="/misc/goto?guid=4958521774130662059" rel="nofollow" target="_blank">Shopify</a> (一家电子商务平台公司)的团队。</li>      <li><strong>What:</strong></li>     </ul>     <p>        + 在 JavaScript 中实现 MVC,几乎是专门为 Rails+CoffeeScript 开发者定制的,MIT 许可。</p>     <p>        + 是所有框架中强制性规定最多的。你必须遵守其约定(例如,怎么组织文件和 URL)。否则,就像他们幻灯片中说的,“你还是用其他框架吧”。</p>     <p>        + 非常完善的框架,具有相当丰富的模型、视图和控制器,还有路由。当然,还有可观察机制。</p>     <p>        + 基于 DOM 的模板。</p>     <ul>      <li><strong>Why:</strong> 如果你使用 Rails 和 CoffeeScript,你找到亲人了。</li>      <li><strong>Where:</strong> <a href="/misc/goto?guid=4958521774228410855" rel="nofollow" target="_blank">GitHub</a> 和 <a href="/misc/goto?guid=4958328912564440127" rel="nofollow" target="_blank">自有站点</a>。</li>      <li><strong>When:</strong> 当前版本 0.9,几个月内将发布1.0版。</li>     </ul>     <p>        <strong>CanJS</strong></p>     <ul>      <li><strong>Who:</strong> <a href="/misc/goto?guid=4958521774348876981" rel="nofollow" target="_blank">Bitovi</a>(一家 JavaScript 咨询/培训公司)的团队。</li>      <li><strong>What:</strong></li>     </ul>     <p>        + 用 JavaScript 实现 MVC,MIT 许可。</p>     <p>        + REST 可持久模型、基本的路由、基于字符串的模板。</p>     <p>        + 知名度不高(我也是上周才听说它的),但它的前身却是原来的 <a href="/misc/goto?guid=4958340973592435442" rel="nofollow" target="_blank">JavaScriptMVC 项目</a>。</p>     <ul>      <li><strong>Why</strong>: 旨在集上述各技术门派之所长,提供与它们类似的功能,同时又保持体积小巧。</li>      <li><strong>Where:</strong> <a href="/misc/goto?guid=4958521774472952655" rel="nofollow" target="_blank">GitHub</a> 和 <a href="/misc/goto?guid=4958521774565283666" rel="nofollow" target="_blank">自有站点</a>。</li>      <li><strong>When:</strong> 1.0 版已经发布了。</li>     </ul>     <p>        <strong>总结</strong></p>     <p>        如果你正在考虑选型的问题,想知道上面这些框架/库中的哪一个最适合你的新项目,那我建议你重点关注以下两点。</p>     <p>        <strong>功能范围</strong>。你想让这个框架或库为你做多少事儿?你的项目是从头做起,因而需要一个能贯穿始终的完整的各项功能齐备的架构吗?或者,你其实更喜欢自己来挑选模式和库?对不同的项目,不同的团队,任何选择都有价值,都是正确的。</p>     <p>        <strong>设计美学</strong>。你看过它们的代码吗,用没用过自己选择的框架构建出了一些小巧的应用?你喜欢这样做吗?不要只看 它们的说明或者功能列表就作出选择:那些信息有价值,但不全面。打个比方,如果你置自己主观的编码经验于不顾,那就像在选择小说时只看它有几章几节,或者 在找对象时只看其简历或个人描述。</p>     <p>        尽管存在分歧,但我认为所有技术门派有一个重大的共性:它们都践行了模型与视图分离的思想。而这个思想早在 Web 诞生之前就已存在,到现在差不多有 20 年历史了。这么说吧,就算你只做一个基本的 Web 应用的 UI,在客户端应用这一思想也永远是正确的。</p>     <p>        原文链接:<a href="/misc/goto?guid=4958521772149889670" rel="nofollow" target="_blank">Rich JavaScript Applications – the Seven Frameworks</a>    </p>     <p>        作者:Steven Sanderson</p>     <p>        翻译:<a href="/misc/goto?guid=4958521772359664610" rel="nofollow" target="_blank">@李松峰</a></p>     <div id="come_from">     来自:      <a id="link_source2" href="/misc/goto?guid=4958521774688096246" target="_blank">www.ituring.com.cn</a>     </div>    </div>