我想给App做个topbar,当是电脑端用手机浏览器器打开时候,就显示topbar,当在APP中打开时候,不显示topbar

帮助企业打造成功软件!
热门搜索:
Axure运用:使用Axure创建iPhone应用程序原型(二)
Axure运用:使用Axure创建iPhone应用程序原型(二)
| 作者:慧都控件网 |
09:59:38| 阅读 0次
概述:在上文中,作者就如何使用iPhone应用程序页面模板讲起,为大家介绍了使用Axure创建iPhone应用程序原型的第一步。下面,作者将继续为大家讲解如何在iPhone上查看你的应用程序原型。
在上篇文章中,作者为大家介绍了如何使用iPhone应用程序页面模板在原型设计工具中创建iPhone程序原型()。在这篇文章中,作者将为大家介绍如何在iPhone上查看你的应用程序原型。在查看原型之前,你需要对你的手机进行设置。
浏览器设置
配置iPhone浏览器选项在生成&原型&移动/设备中。下面看到的设置就是在手机上浏览iPhone应用程序的典型设置。
视窗标签影响移动设备上原型的大小或规模。如果你的程序设计为320像素宽,你就不必再编辑默认的视窗标签设置。&当你进入一个网站链接时&隐藏地址栏&会移除浏览器上面的带状链接地址;&防止垂直页面滚动&让你设计的应用程序不至于从屏幕的边缘拉动。最后,当原型从主屏幕启动时,&隐藏浏览器导航&会移除浏览器按钮。
点击下面的复选框查看在浏览器上的效果
主屏幕图标
主屏幕的图标是一个114px&114px&的PNG图像,它显示在你的iPhone主屏幕上犹如一个真正的应用程序。这种图标可以通过&生成&&&原型&&移动/设备设置&的途径设置。下面的教程演示如何将图标添加到你的iPhone主屏幕上。
注:设计图标时,记住透明区域在手机上浏览时会是一个黑色的背景。
从主屏幕图标启动原型时,启动画面会在你等待加载原型的时候显示。启动图像是一个320px&480pxPNG格式的图像,它可以&生成&原型&移动/设备设置&的途径导入。
如果你的启动画面需要以景观图或水平视图呈现,导入之前请在图形工具中翻转图像。
在iPhone上查看应用程序原型
第一步:生成到AxShare或网络服务器
点击工具栏中的AxShare按钮,将你的原型上传到AxShare,或者在主菜单(按F4)点击&生成&发布到AxShare&。如果你没有AxShare帐户,单击&创建帐户&或进入share.axure.com创建一个免费的账户。点击&发布&上传你的RP文件。你也可以将其发布到自己的Web服务器上。
第二步:点击&显示链接和选项&
接下来,在浏览器中打开你的原型,获取不带网站地图的起始页网址,点击&显示链接和选项&并导航到App主页或包含你应用程序开头的任意页面。复制刚才的URL网址。
第三步:在iPhone浏览器中打开网址
在你的iPhone浏览器中打开刚才的网址,通过电子邮件发送给自己是获得链接的一个好方法。
现在,你可以与你的原型进行交互了,不过此时浏览器的导航仍然是可见的。
第四步:添加到主屏幕
按下位于底部导航中间的&选项&按钮,并选择&添加到主屏幕&。
系统将提示你预览主屏幕图标并要求你选择一个名称。点击&添加&,你就可以从主屏幕启动你的原型,它将显示启动画面,并启动浏览器且不带有底部导航。
在&iPhone&5上查看原型时你可能会遇到屏幕在顶部和底部被截断的情况。调整方法是清除视窗区域中的&宽度&让它成为空白。
本文提供了包含以上设置和合适的参考线的模板可供下载查看。
慧都控件|提供软件技术整体解决方案
云集全球三千余款优秀控件、软件产品,提供行业领先的咨询、培训与开发服务
企业QQ:|电话:023-
服务与支持
重庆 / 023-
北京 / 010-
400-700-1020
慧都旗下网站
慧都科技有限公司 版权所有 Copyright
100%正版软件
400-700-1020
<input type="hidden" id="url" value=""/>额。。最高票答案没答到点子上,最后怎么跑到Nodejs上去了。。Websocket只是协议而已。。&br&我一个个来回答吧&br&&br&&b&一、WebSocket是HTML5出的东西(协议),也就是说HTTP协议没有变化,或者说没关系,但HTTP是不支持持久连接的(长连接,循环连接的不算)&/b&&br&首先HTTP有1.1和1.0之说,也就是所谓的keep-alive,把多个HTTP请求合并为一个,但是Websocket其实是一个新协议,跟HTTP协议基本没有关系,只是为了兼容现有浏览器的握手规范而已,也就是说它是HTTP协议上的一种补充可以通过这样一张图理解&br&&figure&&img src=&https://pic1.zhimg.com/ec133b0e6d7e6d0e194b4c_b.jpg& data-rawwidth=&374& data-rawheight=&133& class=&content_image& width=&374&&&/figure&有交集,但是并不是全部。&br&另外Html5是指的一系列新的API,或者说新规范,新技术。Http协议本身只有1.0和1.1,而且跟Html本身没有直接关系。。&br&通俗来说,你可以用HTTP&b&协议&/b&传输非Html&b&数据&/b&,就是这样=。=&br&再简单来说,&b&层级不一样&/b&。&br&&br&&b&二、Websocket是什么样的协议,具体有什么优点&/b&&br&首先,Websocket是一个&b&持久化&/b&的协议,相对于HTTP这种&b&非持久&/b&的协议来说。&br&简单的举个例子吧,用目前应用比较广泛的PHP生命周期来解释。&br&1) HTTP的生命周期通过Request来界定,也就是一个Request 一个Response,那么&b&在&/b&HTTP1.0&b&中&/b&,这次HTTP请求就结束了。&br&在HTTP1.1中进行了改进,使得有一个keep-alive,也就是说,在一个HTTP连接中,可以发送多个Request,接收多个Response。&br&但是请记住 Request = Response , 在HTTP中永远是这样,也就是说一个request只能有一个response。而且这个response也是&b&被动&/b&的,不能主动发起。&br&&br&&b&教练,你BB了这么多,跟Websocket有什么关系呢?&/b&&br&_(:з」∠)_好吧,我正准备说Websocket呢。。&br&首先Websocket是基于HTTP协议的,或者说&b&借用&/b&了HTTP的协议来完成一部分握手。&br&在握手阶段是一样的&br&-------以下涉及专业技术内容,不想看的可以跳过lol:,或者只看加黑内容--------&br&首先我们来看个典型的Websocket握手(借用Wikipedia的。。)&br&&div class=&highlight&&&pre&&code class=&language-text&&GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com
&/code&&/pre&&/div&熟悉HTTP的童鞋可能发现了,这段类似HTTP协议的握手请求中,多了几个东西。&br&我会顺便讲解下作用。&br&&div class=&highlight&&&pre&&code class=&language-text&&Upgrade: websocket
Connection: Upgrade
&/code&&/pre&&/div&这个就是Websocket的核心了,告诉Apache、Nginx等服务器:&b&注意啦,窝发起的是Websocket协议,快点帮我找到对应的助理处理~不是那个老土的HTTP。&/b&&br&&div class=&highlight&&&pre&&code class=&language-text&&Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
&/code&&/pre&&/div&首先,Sec-WebSocket-Key 是一个Base64 encode的值,这个是浏览器随机生成的,告诉服务器:&b&泥煤,不要忽悠窝,我要验证尼是不是真的是Websocket助理。&/b&&br&然后,Sec_WebSocket-Protocol 是一个用户定义的字符串,用来区分同URL下,不同的服务所需要的协议。简单理解:&b&今晚我要服务A,别搞错啦~&/b&&br&最后,Sec-WebSocket-Version 是告诉服务器所使用的Websocket Draft(协议版本),在最初的时候,Websocket协议还在 Draft 阶段,各种奇奇怪怪的协议都有,而且还有很多期奇奇怪怪不同的东西,什么Firefox和Chrome用的不是一个版本之类的,当初Websocket协议太多可是一个大难题。。不过现在还好,已经定下来啦~大家都使用的一个东西~ 脱水:&b&服务员,我要的是13岁的噢→_→&/b&&br&&br&然后服务器会返回下列东西,表示已经接受到请求, 成功建立Websocket啦!&br&&div class=&highlight&&&pre&&code class=&language-text&&HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat
&/code&&/pre&&/div&这里开始就是HTTP最后负责的区域了,告诉客户,我已经成功切换协议啦~&br&&div class=&highlight&&&pre&&code class=&language-text&&Upgrade: websocket
Connection: Upgrade
&/code&&/pre&&/div&依然是固定的,告诉客户端即将升级的是Websocket协议,而不是mozillasocket,lurnarsocket或者shitsocket。&br&然后,Sec-WebSocket-Accept 这个则是经过服务器确认,并且加密过后的 Sec-WebSocket-Key。服务器:&b&好啦好啦,知道啦,给你看我的ID CARD来证明行了吧。。&/b&&br&后面的,Sec-WebSocket-Protocol 则是表示最终使用的协议。&br&&br&至此,HTTP已经完成它所有工作了,接下来就是完全按照Websocket协议进行了。&br&具体的协议就不在这阐述了。&br&------------------技术解析部分完毕------------------&br&&br&&figure&&img src=&https://pic2.zhimg.com/afe119b52eedabc2dfa9661_b.jpg& data-rawwidth=&161& data-rawheight=&187& class=&content_image& width=&161&&&/figure&你TMD又BBB了这么久,那到底Websocket有什么鬼用,http long poll,或者ajax轮询不都可以实现实时信息传递么。&br&&figure&&img src=&https://pic1.zhimg.com/edb1ed826e264_b.jpg& data-rawwidth=&176& data-rawheight=&193& class=&content_image& width=&176&&&/figure&&br&&br&好好好,年轻人,那我们来讲一讲Websocket有什么用。&br&来给你吃点胡(苏)萝(丹)卜(红)&br&&figure&&img src=&https://pic4.zhimg.com/31ddf0cfbeecefb5f1ff_b.jpg& data-rawwidth=&53& data-rawheight=&65& class=&content_image& width=&53&&&/figure&&b&三、Websocket的作用&/b&&br&在讲Websocket之前,我就顺带着讲下 long poll 和 ajax轮询 的原理。&br&首先是 ajax轮询 ,ajax轮询 的原理非常简单,让浏览器隔个几秒就发送一次请求,询问服务器是否有新信息。&br&场景再现:&br&客户端:啦啦啦,有没有新信息(Request)&br&服务端:没有(Response)&br&客户端:啦啦啦,有没有新信息(Request)&br&服务端:没有。。(Response)&br&客户端:啦啦啦,有没有新信息(Request)&br&服务端:你好烦啊,没有啊。。(Response)&br&客户端:啦啦啦,有没有新消息(Request)&br&服务端:好啦好啦,有啦给你。(Response)&br&客户端:啦啦啦,有没有新消息(Request)&br&服务端:。。。。。没。。。。没。。。没有(Response) ---- loop&br&&br&long poll &br&long poll 其实原理跟 ajax轮询 差不多,都是采用轮询的方式,不过采取的是阻塞模型(一直打电话,没收到就不挂电话),也就是说,客户端发起连接后,如果没消息,就一直不返回Response给客户端。直到有消息才返回,返回完之后,客户端再次建立连接,周而复始。&br&场景再现&br&客户端:啦啦啦,有没有新信息,没有的话就等有了才返回给我吧(Request)&br&服务端:额。。
等待到有消息的时候。。来 给你(Response)&br&客户端:啦啦啦,有没有新信息,没有的话就等有了才返回给我吧(Request) -loop&br&&br&从上面可以看出其实这两种方式,都是在不断地建立HTTP连接,然后等待服务端处理,可以体现HTTP协议的另外一个特点,&b&被动性&/b&。&br&何为被动性呢,其实就是,服务端不能主动联系客户端,只能有客户端发起。&br&简单地说就是,服务器是一个很懒的冰箱(这是个梗)(不会、不能主动发起连接),但是上司有命令,如果有客户来,不管多么累都要好好接待。&br&&br&说完这个,我们再来说一说上面的缺陷(原谅我废话这么多吧OAQ)&br&从上面很容易看出来,不管怎么样,上面这两种都是非常消耗资源的。&br&ajax轮询 需要服务器有很快的处理速度和资源。(速度)&br&long poll 需要有很高的并发,也就是说同时接待客户的能力。(场地大小)&br&所以ajax轮询 和long poll 都有可能发生这种情况。&br&&br&&b&客户端:啦啦啦啦,有新信息么?&/b&&br&&b&服务端:月线正忙,请稍后再试(503 Server Unavailable)&/b&&br&&b&客户端:。。。。好吧,啦啦啦,有新信息么?&/b&&br&&b&服务端:月线正忙,请稍后再试(503 Server Unavailable)&br&&/b&&br&&b&客户端:&/b&&figure&&img src=&https://pic1.zhimg.com/7c0cf075c7ee4cc6cf52fc10_b.jpg& data-rawwidth=&143& data-rawheight=&50& class=&content_image& width=&143&&&/figure&&br&&b&然后服务端在一旁忙的要死:冰箱,我要更多的冰箱!更多。。更多。。(我错了。。这又是梗。。)&/b&&br&&br&--------------------------&br&&b&言归正传,我们来说Websocket吧&/b&&br&通过上面这个例子,我们可以看出,这两种方式都不是最好的方式,需要很多资源。&br&一种需要更快的速度,一种需要更多的'电话'。这两种都会导致'电话'的需求越来越高。&br&哦对了,忘记说了HTTP还是一个无状态协议。(感谢评论区的各位指出OAQ)&br&通俗的说就是,服务器因为每天要接待太多客户了,是个&b&健忘鬼&/b&,你一挂电话,他就把你的东西全忘光了,把你的东西全丢掉了。你第二次还得再告诉服务器一遍。&br&&br&所以在这种情况下出现了,Websocket出现了。&br&他解决了HTTP的这几个难题。&br&首先,&b&被动性&/b&,当服务器完成协议升级后(HTTP-&Websocket),服务端就可以主动推送信息给客户端啦。&br&所以上面的情景可以做如下修改。&br&客户端:啦啦啦,我要建立Websocket协议,需要的服务:chat,Websocket协议版本:17(HTTP Request)&br&服务端:ok,确认,已升级为Websocket协议(HTTP Protocols Switched)&br&客户端:麻烦你有信息的时候推送给我噢。。&br&服务端:ok,有的时候会告诉你的。&br&服务端:balabalabalabala&br&服务端:balabalabalabala&br&服务端:哈哈哈哈哈啊哈哈哈哈&br&服务端:笑死我了哈哈哈哈哈哈哈&br&&br&就变成了这样,只需要经过&b&一次HTTP请求&/b&,就可以做到源源不断的信息传送了。(在程序设计中,这种设计叫做回调,即:你有信息了再来通知我,而不是我傻乎乎的每次跑来问你)&br&这样的协议解决了上面同步有延迟,而且还非常消耗资源的这种情况。&br&那么为什么他会解决服务器上消耗资源的问题呢?&br&其实我们所用的程序是要经过两层代理的,即&b&HTTP协议在Nginx等服务器的解析下&/b&,然后再传送给相应的&b&Handler(PHP等)&/b&来处理。&br&简单地说,我们有一个非常快速的接&b&线员(Nginx)&/b&,他负责把问题转交给相应的&b&客服(Handler)&/b&。&br&本身&b&接线员基本上速度是足够的&/b&,但是每次都卡在&b&客服(Handler)&/b&了,老有&b&客服&/b&处理速度太慢。,导致客服不够。&br&Websocket就解决了这样一个难题,建立后,可以直接跟接线员建立持&b&久连接&/b&,有信息的时候客服想办法通知接线员,然后&b&接线员&/b&在统一转交给客户。&br&这样就可以解决客服处理速度过慢的问题了。&br&&br&同时,在传统的方式上,要不断的建立,关闭HTTP协议,由于HTTP是非状态性的,每次都要&b&重新传输identity info(鉴别信息)&/b&,来告诉服务端你是谁。&br&虽然接线员很快速,但是每次都要听这么一堆,效率也会有所下降的,同时还得不断把这些信息转交给客服,不但浪费客服的&b&处理时间&/b&,而且还会在网路传输中消耗&b&过多的流量/时间。&/b&&br&但是Websocket只需要&b&一次HTTP握手,所以说整个通讯过程是建立在一次连接/状态中&/b&,也就避免了HTTP的非状态性,服务端会一直知道你的信息,直到你关闭请求,这样就解决了接线员要反复解析HTTP协议,还要查看identity info的信息。&br&同时由&b&客户主动询问&/b&,转换为&b&服务器(推送)有信息的时候就发送(当然客户端还是等主动发送信息过来的。。)&/b&,没有信息的时候就交给接线员(Nginx),不需要占用本身速度就慢的&b&客服(Handler)&/b&了&br&--------------------&br&至于怎么在不支持Websocket的客户端上使用Websocket。。答案是:&b&不能&/b&&br&但是可以通过上面说的 long poll 和 ajax 轮询来 &b&模拟出类似的效果&/b&&br&-----&br&_(:з」∠)_两天写了两篇科普类文章。。好累OAQ,求赞。。&br&对啦,如果有错误,欢迎大家在底下留言指出噢~
额。。最高票答案没答到点子上,最后怎么跑到Nodejs上去了。。Websocket只是协议而已。。 我一个个来回答吧 一、WebSocket是HTML5出的东西(协议),也就是说HTTP协议没有变化,或者说没关系,但HTTP是不支持持久连接的(长连接,循环连接的不算) 首先HTTP…
来点干货吧,转载我自己的文字,&a href=&//link.zhihu.com/?target=http%3A//qthyzg.vip.blog.163.com/blog/static//& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&超级简单实用的壮阳法!&/a& 原文最初发在大斌健美论坛。&br&&br&所谓的什么体育运动,不如划分一下,哪些动作对男性能力提升较好,然后整理哪种运动形式这些动作较多,答案也就出来了。&br&&br&以下为原文捞干之后的内容。&br&&br&&blockquote&一、对于助性的方法来说,首先因素是心情,其次是双方感情,大斌这里不是家庭和情感论坛,这些刨除之后,就要看内需,就是双方有没有需求,然后是有了需求之后,能否响应,所谓有心无力也白搭!&br&&br&二、对于充斥论坛的大重量深蹲助性论,我个人一直认为那个是心理暗示,就我个人而言,大重量深蹲后,内需很平淡。目前为止还是分享经验为主,个人经验和在男会员身上实践的结论,如果想助性,很简单,一对单只自身体重六分之一以内的哑铃,对大多数人而言,单只10-20公斤左右的哑铃,抗在肩上做深蹲推举,5-8次*10-15组,总体十五分钟以内,可以配合俯卧撑和下拉等整体动作练习。&br&&br&检验标准很简单:练完之后,找个没人地方掀开裤子,看看里面的兄弟是蠢蠢欲动,蓬勃待发,还是萎靡不振,毫无生气!&br&&br&有性经验的人,应该知道由于各种原因,不是每次都是“怒胀”,说白了,就是起来之后,也是时大时小的,而怒胀对于整体质量的提高,是毫无疑问的。如果你次次怒胀,恭喜恭喜,你很性福!&br&&br&感兴趣的建议看看素女经,里面对交合的过程和男性反应做了分阶段的描述和说明。&br&&br&互联网上有句话:在伟哥之前,威尔刚的出现,证明了“尺寸不是问题,硬度才是关键!”&br&&br&三,除了训练之外,有没有拉动内需的方法呢?据说道士、藏密僧侣、瑜伽行者性能力最好,他们可没有每天杠铃哑铃不离身。老祖宗留给我们的财富是:人可以通过吐纳导引改善自己!&br&&br&我将这个方法分成一个三周计划,按周执行。普通人,根据体质不同,最短三天,最长半个月,从晨勃强度密度,以及精力变化上就能感觉到是否有效。也就是说,不信的话,不妨坚持两周试试,女士练这个的话,效果另说,至少没坏处!&br&&br&第一周:每天抽时间,全天弯腰俯身(体前屈)十次,不要一次做完,想起来就做,饭后一个小时再做。弯腰俯身的时候,上身降到自己舒服的位置为宜,能够到地面的到地面,能到膝盖的到膝盖,感觉后背和腿舒服的淡淡拉伸为宜。&br&&br&谨记要点是:腿要保持伸直,不要弯曲;头要自然下垂,几乎与地面垂直,这样你脊柱才能得到最大刺激,此动作可以缓解颈腰劳损拉伤,改善面容血色,按摩内脏。&br&&br&八段锦第六式,“双手攀足固腰肾”就是这个动作,细节有差别,现代医学认为这个动作可以促进血液循环和改善脑垂体分泌,从而刺激性欲。&br&&br&第二周:每天抽时间,全天十五次弯腰俯身,每次数两个呼吸,也就是弯腰后,悠长缓慢呼吸两次再起来;晚上临睡前,除去上衣,下裤下降,露出腰际。双手手心对搓36次搓热后,双手手心捂在后腰左右两侧上,上下搓36次,然后手心再次36次对搓搓热,捂在后腰两侧,十秒左右,完工。&br&&br&为啥是36次?中医跟“易”密不可分,易与术数有关,对普通人而言,只要知道这是个大概数字就行,有人搓的慢有人搓的快,大致这么多下就是,也就是两分钟左右的事情。&br&&br&搓肾,是传统医学中最常见的手法,与道家相关技术异曲同工,网络上很多关于它的描述,注意的是,道家描述男人时,肾有两种,内肾和外肾,外肾是阴囊和睾丸,道家有很多“兜外肾”的功法。&br&&br&第二周晚上的工作,可以提前至第一周做,关键是考虑体质差别和一次吃太多坚持不来。健身房若干个人连三五天都坚持不下来,坚持下来的赞不绝口,这是题外话。&br&&br&第三周:每天还是全天十五次弯腰俯身,想起来就做,只不过如今每次俯身的时候,数四至六个呼吸,视个人体质而定;晚上的搓肾照常。&br&&br&好了,如果你能坚持三周,是否有变化应该心中有数了,以后是否长期坚持也是个人的事情。这套动作,简单实用,不需要呼吸法不需要收束法,每天三五分钟的,对于拉动内需改善质量来说,足够了!&br&&br&效果,那是相当的好!&br&&br&&strong&两件重要的事情!&br&&br&1.部分兄弟练几天后,晚上会有遗精现象,不用管,继续练就行。可以有性生活,但是建议禁欲半个月,呵呵。&br&&br&2.有前列腺炎的人,练几天后会阴部会不舒服,还会有尿频症状,不用管,坚持下去前列腺炎都能缓解。&/strong&&/blockquote&
来点干货吧,转载我自己的文字, 原文最初发在大斌健美论坛。 所谓的什么体育运动,不如划分一下,哪些动作对男性能力提升较好,然后整理哪种运动形式这些动作较多,答案也就出来了。 以下为原文捞干之后的内容。 一、对于助性的方法…
这是个Meta级别的好问题!如果你想把web前端性能优化到极致,一定要认真地去了解这个原则背后的原理,而非表面的技巧。&br&&br&&b&(已完结,转载请署名,否则保留追究的权利)&/b&&br&&br&事实上,如果对web优化比较了解,只要一句话就能说清楚了。&b&web页面性能优化其精髓就是——将浏览器基本无序的资源加载请求用js有序地控制起来,包括js本身。&/b&&br&&br&这个原则几乎适用于所有web场景,只是它演变出来的具体做法千差万别,PC端和H5端由于环境不一样,也要有不同的玩法,而Bigpipe也是基于这个理念。但请问你能理解吗?&br&&br&如果你能理解,那么可以不往下看,如果不能理解,建议看看,或许有收获的。&b&我主要以PC端几个知名电商网站的优化为案例,来说明将js放在html不同位置都有什么不同。&/b&&br&&br&-----------&br&&b&一、为什么我会认为这是个好问题?!&/b&&br&&br&在我带过的几个电商项目前端团队中,就因为这个问题开过几个不开窍的前端。&br&&br&理由很简单,也比较霸道。这几天我们项目又在做前端性能优化,又有同事拿着这个疑惑来问我,呵呵,不会再乱开人了。&br&&br&以前为此开人,可能是我没能力用通俗易懂的文字来描述好这个问题,难免有误伤。为了避免这样的事情,我决定要好好把问题说清楚,就从浏览器渲染的原则开始!&br&&br&&b&二、是不是网页JS调用都尽量放到网页底部?&/b&&br&&br&按知乎的原则,先要问是不是,再问为什么,但这个'是不是'对于做前端技术的人来说,一眼就能看出个所以然。&br&&br&显然,不是的!但性能优化做得好的网站基本上是这个原则。给两个我认为前端优化做得比较好的知名海淘类电商,大家去观摩一下别人的做法:&br&&br&-----------&br&&a href=&//link.zhihu.com/?target=http%3A//www.kaola.com/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&网易考拉海购!&/a&&br&&a href=&//link.zhihu.com/?target=http%3A//www.beibei.com/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&贝贝网&/a&&br&-----------&br&&br&当然,我们不能用Bigpipe这种极端的优化技术流派来解答,或许是解答不了的,但即便是bigpipe其背后的原理也是和这个原则并没有冲突的,大道至简,底层的原理是一样的,只是它尽全力地利用每一次http请求,用前端的技术手段来加载足够多的资源。&br&&br&当然了,题主应该是一个前端开发,而且应该是在碰到页面优化需求或学习上的疑惑了,可能有人强逼这TA按照这样的原则去做,但又不知道什么别人为啥要求他这么做,于是就有了这个问题!&br&&br&至于情况是不是这样的,我只是瞎猜的。但是,我带的前端团队里面有不少同学存在同样的疑惑,因为我有这样一个规范:&br&&figure&&img src=&https://pic1.zhimg.com/5c60aba0f28_b.png& data-rawwidth=&757& data-rawheight=&753& class=&origin_image zh-lightbox-thumb& width=&757& data-original=&https://pic1.zhimg.com/5c60aba0f28_r.png&&&/figure&不知道有多少团队有这样的标准化demo模板规范?这是我1年多以前做的了,在这里——&a href=&//link.zhihu.com/?target=http%3A//pjg.pw/framework/front-end-dev-docc.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&基于gulp的前端框架开发规范&/a&。大家可以去我的博客看看,权当参考。当然,现在这个规范已经有了新版本。&br&&br&--------------------&br&&b&三、为什么网页JS调用都尽量放到网页底部?&/b&&br&&br&这部分如果《高性能网站建设指南》这本书上有详细说明的并且我也认同的,就直接截图贴过来,这里我只说自己的理解部分。还有,对于书本上的东西,我的态度是——尽信书,不如无书。&br&&br&&b&(一)大家的做法是不是一样的?&/b&&br&&br&ok,我先把问题分解一下。&br&&br&首先这里有个关键词——尽量。《高性能网站建设指南》这本书里面用的词是“如果可以的话”。&br&&figure&&img src=&https://pic2.zhimg.com/2a9ffa963cb71fb98e36ca69_b.jpg& data-rawwidth=&711& data-rawheight=&337& class=&origin_image zh-lightbox-thumb& width=&711& data-original=&https://pic2.zhimg.com/2a9ffa963cb71fb98e36ca69_r.jpg&&&/figure&&br&也就是说,js不完全是一定要放在页面底部的,但是你要了解清楚以下两个问题了:&br&&ol&&li&&b&什么是尽量的(可以的)那部分js代码?&/b&&br&&/li&&li&&b&什么是不尽量的&b&(不可以的)&/b&那部分呢?&/b&&br&&/li&&/ol&只有了解清楚这两个问题,你才知道如何去安排js在页面中的位置。ok,我们来看看考拉网和贝贝网的首页源代码。&br&&ol&&li&&b&考拉网:&/b&&head&&/head &之间就一段让IE9以下浏览器兼容HTML5标签的js代码,这是一个底层的兼容脚本,不涉及任何页面逻辑,而它的全部页面逻辑都是放置在脚步。&br&&/li&&li&&b&贝贝网:&/b&&head&&/head &之间放置的是一些全局设置和一些统计脚本,也不涉及页面逻辑,逻辑部分js也是放在页面底部。&br&&/li&&li&&b&我们项目的:&/b&做法是两者的结合,heah标签内就的js脚本就只是定义几个全局的命名空间和一段统计脚本,没了,而业务逻辑js就放置页面最底部。&/li&&/ol&&figure&&img src=&https://pic2.zhimg.com/a337d5d4b8164a7befaf84af8b56bc15_b.jpg& data-rawwidth=&789& data-rawheight=&500& class=&origin_image zh-lightbox-thumb& width=&789& data-original=&https://pic2.zhimg.com/a337d5d4b8164a7befaf84af8b56bc15_r.jpg&&&/figure&&br&整体对比来看,css样式规划大家都基本相同,是1个全局+1个当前,文件名上通过md5戳来解决强缓存问题,js的缓存解决方案也是一样的做法。&br&&figure&&img src=&https://pic2.zhimg.com/805edad04af25_b.png& data-rawwidth=&486& data-rawheight=&318& class=&origin_image zh-lightbox-thumb& width=&486& data-original=&https://pic2.zhimg.com/805edad04af25_r.png&&&/figure&&br&这是我们的PC端js的大致布局。考拉网也是类似分配方式,只是把core和common合并在一起(超过了200K),我们没有。我是觉得合并在一起这样模块太大了,不太利于弱网用户,但多一次http请求,有利有弊吧。&br&&figure&&img src=&https://pic3.zhimg.com/9d4d8507b2_b.jpg& data-rawwidth=&953& data-rawheight=&646& class=&origin_image zh-lightbox-thumb& width=&953& data-original=&https://pic3.zhimg.com/9d4d8507b2_r.jpg&&&/figure&&br&有部分人可能会问,为啥不统统合并在一起,就1个HTTP请求了?我只能呵呵,网站不是只有1个首页,还有很多其他页面呢,只要把js底层库和常用的公共类库加载一次,其他页面就可以被缓存起来(form cache或304)&br&&br&这个前端技术表面的对比,是不是有点意思呢?&br&&br&我们几个都是海淘类垂直电商,只是定位和强势品类有些小差别,但在业务层面其实是基本相同的,都是海淘。也就是说,我们互为竞争对手!那么,很显然我们不可能相互沟通、开会,然后通报我用什么前端架构,前后端协作开发的模式等等技术问题,但是为什么做法上大家是那么的一致呢?&br&&br&这就是问题了!我绝对保证不认识考拉的前端架构设计师,但我的前端设计方案出来的结果几乎是一模一样的!为什么呢?&br&&br&简单点说,条条道路通罗马。就这样,没为什么。后面我汇以网易考拉为案例,逆向分析他们的做法,进而尝试窥探他们的前端架构设计方案。不一定正确,只是个人看法。&br&&br&如果你想得到绝对正确的答案,就想办法进入里面,或者发一个类似这样的问题(&a href=&http://www.zhihu.com/question/& class=&internal&&美团的前端架构是怎样的? - 前端开发&/a&),看看有没有人出来回复。&br&&br&&b&-------日22:56:43---------&br&&/b&&b&这里上一个简单的web优化对比图(&a href=&//link.zhihu.com/?target=http%3A//www.alibench.com/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&阿里测,专业的网站即时探测工具&/a&&/b&&b&):&/b&&br&&figure&&img src=&https://pic2.zhimg.com/96f3eb9fceb9be6a6df6525_b.jpg& data-rawwidth=&1024& data-rawheight=&1698& class=&origin_image zh-lightbox-thumb& width=&1024& data-original=&https://pic2.zhimg.com/96f3eb9fceb9be6a6df6525_r.jpg&&&/figure&对比只是一个参考,不见得我们的技术开发人员实力很好,很多就是一般水平的。而且电商的竞争很多时候不仅仅是技术力量的角力,还有产品理念,运营能力,市场推广等等综合因素决定的,技术只是基础,特别是后进场的玩家,我们的项目上线才4个多月,我不想透露太多,避免中枪。&br&&br&这里是显摆的,我们项目最近优化的结果:&br&&figure&&img src=&https://pic2.zhimg.com/c11a932ee11ad6b421fd9_b.png& data-rawwidth=&1029& data-rawheight=&508& class=&origin_image zh-lightbox-thumb& width=&1029& data-original=&https://pic2.zhimg.com/c11a932ee11ad6b421fd9_r.png&&&/figure&&b&这次的优化心得:&/b&&br&由于我们运营增加了2个第三方统计,是的我们对第三方静态内容缓存控制力度下降了,但是我们改善了gzip和图片的压缩优化,比前几天提高了几分,但我认为还有优化空间,比如:&br&&ul&&li&css用到的雪碧图的压缩比例还不够,需要改进前端构建框架,改进图片压缩的算法,下个星期上一个行版本,看看效果&br&&/li&&li&html文档并没有迷你化,要将服务端的模板弄到前端构建流程里面,控制起来做压缩,这个有利有弊,利就是可以在发布到服务端前作压缩,弊端就是迷你化后不太方便调试&/li&&/ul&这两点弄好了,上90分应该不成问题。如果也是做这一块的,可以将经验分享出来,相互学习。我们和考拉网的代码量几乎一致,交互也基本相同,有一定对比价值。&br&&br&----------&br&&b&这里必须补充一点:&/b&&br&&b&用类似&a href=&//link.zhihu.com/?target=http%3A//www.alibench.com/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&阿里测&/a&这种工具来对比,只能作为一种参考,如果大家的业务不同,页面的Dom数量差异太多,且交互场景也有很大差别,那么这种对比是没有任何意义的。&/b&&br&----------&br&&br&&b&(二)js在页面中不同位置带来的影响或效果区别&/b&&br&&br&(这里将是讲浏览器资源加载原理和js执行原理的,用通俗易懂的方式说明白需要死掉很多脑细胞,查阅很多很多资料,可能包括已经还给老师的E文,会慢一点点。我争取说得通俗易懂,但发现很难,大家要有心理准备。)&br&&br&要彻底搞懂,为什么别人建议js放在页面的底部,那么我需要从js的语言机制及其运行环境说起。&br&&br&&b&1,浏览器不是单线程的,它多线程的,如果有必要它还是多进程的。&/b&&br&&br&很多同学并不理解浏览器不是单线程的,别问我为什么,暂时不打算做代课老师,这里有两篇,自己去理解。&br&&br&&a href=&//link.zhihu.com/?target=http%3A//ued.ctrip.com/blog/%3Fp%3D3287& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&浏览器是怎样工作的(一):基础知识&/a&&br&&a href=&//link.zhihu.com/?target=http%3A//ued.ctrip.com/blog/%3Fp%3D3295& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&浏览器是怎样工作的:渲染引擎,HTML解析(连载二)&/a&&br&&br&例如,Webkit或是Gecko引擎,都可能有如下线程:&br&&ul&&li&javascript引擎线程&br&&/li&&li&界面渲染线程&br&&/li&&li&浏览器事件触发线程&br&&/li&&li&Http请求线程&/li&&/ul&&b&&br&2,js是单线程的&/b&&br&&br&证明的脚本:&br&&figure&&img src=&https://pic1.zhimg.com/d4668c35dba4e13e5eefb0_b.jpg& data-rawwidth=&576& data-rawheight=&319& class=&origin_image zh-lightbox-thumb& width=&576& data-original=&https://pic1.zhimg.com/d4668c35dba4e13e5eefb0_r.jpg&&&/figure&&br&在1万次循环迭代过程中,foo()一直先打印了1万次‘first’,定时时间执行时间为0,它也不去执行里面的mylog函数,而是等待循环结束后,再输出1万次‘second’,看起来像运行了两次迭代,是不是表现很怪异?&br&&br&为什么?&br&&br&因为&strong&JS运行在浏览器中,是单线程的,每个浏览器页面就是一个JS线程&/strong&,既然是单线程的,在某个特定的时刻只有特定的代码能够被执行,并阻塞其它的代码。而浏览器是多线程的,它又一个名叫&strong&Event driven(&/strong&&strong&事件驱动&/strong&&strong&)的线程,而且浏览器&/strong&&b&具备&/b&&strong&Asynchronized(&/strong&&strong&异步&/strong&&strong&)&/strong&执行事件的特性,会创建事件并放入执行队列中,异步执行。&br&&br&浏览器定义的异步事件有很多种,例如mouse click(鼠标点击事件), a timer firing(定时器触发事件), 或者an XMLHttpRequest completing(XMLHttpRequest完成回调事件),一旦js代码中有这样的事件代码,浏览器就会将它们放入执行队列,等待当前js代码执行完成之后,再按队列情况逐个执行。&br&&br&于是,我们就看到了上面的
setTimeout(mylog, 0);
这段代码被执行的怪异表现了,也就是mylog的执行顺序被改变了。&br&&blockquote&一个有用的知识点: setTimeout(func, 0)的作用&br&&ul&&li&让浏览器渲染当前的变化(很多浏览器UI render和js执行是放在一个线程中,线程阻塞会导致界面无法更新渲染)&/li&&li&重新评估”script is running too long”警告&/li&&li&改变代码块的执行顺序&/li&&/ul&&/blockquote&&b&3,浏览器对资源的加载是线性的,可并行的,但js除外&/b&&br&&br&当我们在浏览器的地址栏里输入一个url地址,访问一个新页面时候,页面展示的快慢就是由一个单线程所控制,这个线程叫做UI线程,UI线程会根据页面里资源(资源是html文件、图片、css等)书写的先后顺序,它会按照资源的类型发起http请求来获取资源,当http请求处理完毕也就意味着资源加载结束。&br&&br&但是碰到javascript文件则不同,它的加载过程被分为两步,第一步和加载css文件和图片一样,就是执行一个http请求下载外部的js文件,但是javascript完成http操作后并不意味操作完毕,UI线程就会通知javascript引擎线程来执行它,如果javascript代码执行时间过长,那么用户就会明显感觉到页面的延迟。&br&&br&为什么浏览器不能把javascript代码的加载过程拆分为下载和执行两个并行的过程,这样就可以充分利用时间完成http请求,这样不是就能提升页面的加载效率了吗?&br&&br&答案当然是否定的。&br&&br&因为javascript是一个&a href=&//link.zhihu.com/?target=http%3A//baike.baidu.com/view/1757849.htm& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&图灵完备&/a&的编程语言,js代码是有智力的,它除了可以完成逻辑性的工作,还可以通过操作页面元素来改变页面的UI渲染,如果我们忽略javascript对网页UI界面渲染的影响,让它下载和运行是分开的(也可以理解为js代码可以延迟执行),结果会造成页面展示的混乱,或多次重绘。很显然,这样的做法是不合适的,因此,js脚本的下载和执行必须是一个完整的操作,是不能被割裂的。&br&&figure&&img src=&https://pic1.zhimg.com/cba132e50_b.jpg& data-rawwidth=&1436& data-rawheight=&619& class=&origin_image zh-lightbox-thumb& width=&1436& data-original=&https://pic1.zhimg.com/cba132e50_r.jpg&&&/figure&百度首页的资源下载瀑布图(没有任何缓存状态下,所有http请求响应状态都是200)&br&&br&既然拆分js的下载和执行是不可行的,但为了提升用户体验,加快UI线程的执行又是一个无法回避的问题,于是浏览器就换了种方式,让它在同一个时间可以下载多个资源。&br&&br&例如上面百度的截图,在同一个域名下,firefox可以同时下载两种图片(chrome可以同时下载4个静态资源),不过这是针对图片和css文件,对于js文件似乎还是一个接着一个的下载,下载一个执行一个,不过到了js执行时候还是要严格按照顺序执行。当然,我在途中用黄色标记的几个js是并行加载的,其实是先前某个js发起的请求(这种做法就是无阻塞的js加载,也叫异步加载,后面我会说明这个东西有什么好坏)。&br&&br&多个http连接并行下载资源就好比多个线程共同完成某个任务,如果并行http连接更多,那么能有更多http资源同时被下载,但是浏览器提供并行执行的http连接实在太少了,例如上面firefox才两个,chrome也只有4个,那如何突破浏览器的连接个数的限制了?&br&&br&方法很简单就是将常用的,稳定的静态资源统一放在静态资源服务器上,由统一的域名对外提供连接,而这个域名要和主域名不一样就可以了。也就是将静态资源放在CDN节点上,单独用一个域名来对应。&br&&br&到这里,可能有人会问,是不是给每个静态资源分配一个域名,让所有资源都可以并行下载就会达到最佳状态了呢?&br&&br&答案当然也是否定的。简单滴说,有两个方面原因:&br&&br&一方面,我们采用的是http1.1版协议,它的特点是资源下载过程是一个长连接,而长连接的好处是在页面和服务端频繁交互时效率更好,但http协议有时候不是那么的可靠,导致服务器要维护一些无用的长连接,访问的人次越多越糟糕。另一方面,当我们同时在一个页面中使用的域名过多,会导致dns解析的开销增大。&br&&br&那么,多少个域是最合适的呢?好像是雅虎军规中有提过,最佳的建议是2个。也就是图片一个CDN域,css和js一个域。&br&&br&&b&4,&/b&&b&放到网页顶部的js就一定阻塞页面渲染吗?&/b&&br&&br&刚才说了,js之所以会阻塞UI线程的执行,是因为javascript能影响甚至控制UI渲染的过程,而页面加载的规则是要顺序执行,所以在碰到js代码时候UI线程就会通知js引擎来执行它。&br&&br&然而,很早很早以前,很多程序员不知道这个特点或者知道但被忽视,因此导致编写代码时候将用于展示的代码和用于处理逻辑的代码混淆在一起,这样做的后果是使js代码造成的阻塞更加严重,于是业界良心的雅虎出台了这个军规——将js脚本放置到html文档的末尾。&br&&br&如果不想深究这个话题,其实到这里就可以结束了。但是,我个人不是很喜欢按常规套路出牌,比如对于军规进行一个反问——难道将js脚本放置在head部分就一定会阻塞页面渲染吗?&br&&br&答案其实依然是否定的。我简单用常用的jQuery.lazyload插件整了两个简单的测试&br&&br&&a href=&//link.zhihu.com/?target=http%3A//sandbox.runjs.cn/show/mute4dfe& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&sandbox.runjs.cn/show/m&/span&&span class=&invisible&&ute4dfe&/span&&span class=&ellipsis&&&/span&&/a& --&这个是所有js在头部的&br&&a href=&//link.zhihu.com/?target=http%3A//sandbox.runjs.cn/show/bnam8lfs& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&sandbox.runjs.cn/show/b&/span&&span class=&invisible&&nam8lfs&/span&&span class=&ellipsis&&&/span&&/a& --&这个是所有js在尾部的&br&(这里请对比源代码)&br&两者的效果是一致的,但如果我们把js头部的lazyload实例化的脚本改成不放在
$(document).ready() 这个方法里,而是直接实例,那么lazyload就失效了。&br&&div class=&highlight&&&pre&&code class=&language-js&&&span class=&c1&&//原来的&/span&
&span class=&nx&&$&/span&&span class=&p&&(&/span&&span class=&nb&&document&/span&&span class=&p&&).&/span&&span class=&nx&&ready&/span&&span class=&p&&(&/span&&span class=&kd&&function&/span&&span class=&p&&()&/span& &span class=&p&&{&/span&
&span class=&nx&&$&/span&&span class=&p&&(&/span&&span class=&s2&&&img.lazy&&/span&&span class=&p&&).&/span&&span class=&nx&&lazyload&/span&&span class=&p&&();&/span&
&span class=&p&&});&/span&
&span class=&c1&&//如果改成这样,并放在head标签内部,那么lazyload就失效&/span&
&span class=&c1&&//但是如果我们将这个放在所有的img元素以后,那么lazyload就又生效了&/span&
&span class=&nx&&$&/span&&span class=&p&&(&/span&&span class=&s2&&&img.lazy&&/span&&span class=&p&&).&/span&&span class=&nx&&lazyload&/span&&span class=&p&&();&/span&
&/code&&/pre&&/div&&br&为什么会这样?&br&&br&虽然我们将js全部放在头部,但事实上是利用jq的一个延迟执行的接口——$(document).ready() ,让js逻辑( $(&img.lazy&).lazyload(); )的执行延迟到文档准备好了之后,因而保障了lazyload在执行的时候,页面中的img标签是存在的。&br&&br&但是,如果不放在这个接口里面,那么头部的js逻辑就会在文档准备完成之前执行,这时候页面中还没有img元素,因此也就失效了。&br&&br&不过,如果我们将这段实例化的逻辑弄到后面(所有img标签之后),即便不放在$(document).ready里面执行,lazyload就又能生效了。&br&&br&但这个时候,其实这段逻辑依赖的jQuery库和lazyload插件并不需要放在head里面了,而只要保持在实例化的逻辑之前一点点就可以了,而这种做法就是雅虎军规推荐的。&br&&br&当然,这里的结论是&b&“放到网页顶部的js不一定阻塞页面渲染”,只要将实例化的js接口或方法封装在&/b&$(document).ready接口内,这样就可以保障逻辑能够顺利进行。&br&也可以这么写:&br&&div class=&highlight&&&pre&&code class=&language-js&&&span class=&nx&&$&/span&&span class=&p&&(&/span&&span class=&kd&&function&/span&&span class=&p&&(){&/span&
&span class=&nx&&$&/span&&span class=&p&&(&/span&&span class=&s2&&&img.lazy&&/span&&span class=&p&&).&/span&&span class=&nx&&lazyload&/span&&span class=&p&&();&/span&
&span class=&p&&})&/span&
&/code&&/pre&&/div&&br&&b&5,为什么电商网站喜欢将&/b&&b&js逻辑放在脚部呢?&/b&&br&&br&很显然,这并不是海淘电商的前端架构设计者有特殊的癖好,而是业务优化的需要。但是,这个需要结合不同的架构情况来具体分析,如果涉及到需要用前端模板引擎渲染页面的,情况就更加复杂了。&br&&br&比如&a href=&//link.zhihu.com/?target=http%3A//www.vip.com/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&唯品会&/a&,大家先去观摩一下她的首页,是不是有很多类似这样的代码:&br&&div class=&highlight&&&pre&&code class=&language-html&&&span class=&c&&&!-- 导航选择分区浮层 --&&/span&
&span class=&nt&&&script &/span&&span class=&na&&type=&/span&&span class=&s&&&text/html&&/span& &span class=&na&&id=&/span&&span class=&s&&&J_selectArea_list&&/span&&span class=&nt&&&&/span&
&span class=&o&&&&/span&&span class=&nx&&div&/span& &span class=&kr&&class&/span&&span class=&o&&=&/span&&span class=&s2&&&sel-area-box-inner&&/span& &span class=&nx&&id&/span&&span class=&o&&=&/span&&span class=&s2&&&J-areaBinner&&/span&&span class=&o&&&&/span&
&span class=&o&&&&/span&&span class=&nx&&i&/span& &span class=&kr&&class&/span&&span class=&o&&=&/span&&span class=&s2&&&ico-arw&&/span&&span class=&o&&&&&/span&&span class=&err&&/i&&/span&
&span class=&o&&&&/span&&span class=&nx&&p&/span& &span class=&kr&&class&/span&&span class=&o&&=&/span&&span class=&s2&&&sab-tit&&/span&&span class=&o&&&&/span&&span class=&nx&&请选择所在的收货地区&/span&&span class=&o&&&&/span&&span class=&err&&/p&&/span&
&span class=&o&&&&/span&&span class=&nx&&table&/span& &span class=&kr&&class&/span&&span class=&o&&=&/span&&span class=&s2&&&sab-table&&/span& &span class=&nx&&mars_sead&/span&&span class=&o&&=&/span&&span class=&s2&&&home_top_zone_link&&/span&&span class=&o&&&&/span&
&span class=&p&&{&/span&&span class=&err&&#&/span&&span class=&nx&&items&/span&&span class=&p&&}&/span&
&span class=&o&&&&/span&&span class=&nx&&tr&/span&&span class=&o&&&&/span&
&span class=&o&&&&/span&&span class=&nx&&th&/span&&span class=&o&&&&/span&&span class=&p&&{&/span&&span class=&nx&&$sort&/span&&span class=&p&&}&/span&&span class=&o&&&&/span&&span class=&err&&/th&&/span&
&span class=&o&&&&/span&&span class=&nx&&td&/span&&span class=&o&&&&/span&
&span class=&p&&{&/span&&span class=&err&&#&/span&&span class=&nx&&item&/span&&span class=&p&&}&/span&
&span class=&o&&&&/span&&span class=&nx&&span&/span& &span class=&kr&&class&/span&&span class=&o&&=&/span&&span class=&s2&&&J_select_item&&/span& &span class=&nx&&mars_sead&/span&&span class=&o&&=&/span&&span class=&s2&&&te_home_head_diqu_link&&/span& &span class=&nx&&data&/span&&span class=&o&&-&/span&&span class=&nx&&wh&/span&&span class=&o&&=&/span&&span class=&s2&&&{$warehouse}&&/span& &span class=&nx&&data&/span&&span class=&o&&-&/span&&span class=&nx&&id&/span&&span class=&o&&=&/span&&span class=&s2&&&{$id}&&/span&&span class=&o&&&&/span&&span class=&p&&{&/span&&span class=&nx&&$name&/span&&span class=&p&&}&/span&&span class=&o&&&&/span&&span class=&err&&/span&&/span&
&span class=&p&&{&/span&&span class=&err&&#&/span&&span class=&o&&/&/span&&span class=&nx&&item&/span&&span class=&p&&}&/span&
&span class=&o&&&&/span&&span class=&err&&/td&&/span&
&span class=&o&&&&/span&&span class=&err&&/tr&&/span&
&span class=&p&&{&/span&&span class=&err&&#&/span&&span class=&o&&/&/span&&span class=&nx&&items&/span&&span class=&p&&}&/span&
&span class=&o&&&&/span&&span class=&err&&/table&&/span&
&span class=&o&&&&/span&&span class=&err&&/div&&/span&
&span class=&nt&&&/script&&/span&
&span class=&c&&&!-- 导航选择分区浮层 end --&&/span&
&/code&&/pre&&/div&&br&这就是前端模板引擎的标志性代码。那么,就这种情况,我先提出几个疑问:&br&&br&a,请问当页面有大量这样的代码需要处理和维护时,页面中的js到底怎么布置才是合理的呢?&br&b,你不觉得,这样的模板维护起来是不太容易吗?直接放置在页面上,如果这个页面要经常变动(首页显然是变动频率比较高的),前端后端都可能有人来维护这份代码,请问冲突了怎么解决呢?有没有办法将冲突风险降到最低?&br&c,请问如果我们不把这些文件直接放在页面上,比如将它们弄到在某个js里面,这样做可以吗?&br&d,如果要这样做,如何让前端开发人员容易维护这样的代码,比如保存即可看到效果,需要怎样一种前端架构设计来完成这需求呢?&br&&br&&blockquote&&b&严重声明:&/b&&br&1. 这里并不是想拿VIP开刷,而是我真的一时半会找不到更合适、更有代表性的对象了。这些问题涉及前端开发模式选择的问题,这个章节我不打算展开,留给后面的前端架构分析来补充!&br&2. 虽然我觉得VIP的做法还有更好的选择,但并不是说换我去实施就一定比现在负责这一块的同行做得更好,真心不是这样的。电商这一个领域,很多时候业务的实现都是有时限的,特别是VIP这种高速发展的电商,因此这里只是一种局外人的视角,随便说说罢了。&/blockquote&&br&&b&先解决这个问题——&/b&&br&&b&为什么我会说电商喜欢将js放在页面的尾部是因为业务优化的需要呢?&/b&&br&至少我已经找到了3家(就是前面对比的),因此这不是个例。这里要搞清楚“电商的业务优化需要”是什么?&br&&br&首先,我们要知道,电商其实就是和钱打交道的网站,卖东西,然后收钱,本质上和你我他家门口的小卖部没啥两样,只是我们通过网络来进行,而网络这种东西是不透明的,你不知道卖东西的是不是一条狗还是一只猫,当然买东西的一样,大家相互信任的基础是非常薄弱的。&br&&br&好在淘宝等一大批先驱将网络支付的这种文化或习惯培养了起来,我们后进场的电商玩家就要基于各种在线支付手段来完成买卖,但是玩家人数很多啊,而且都不是BAT级别的,本来用户对于这种电商的信任度就比较低,大家对于任何可以提高用户体验的细节都要做到斤斤计较,能有多完美就要多完美。&br&&br&还有很多,但必须打住...我只是为了照顾部分客官,打了这么多废话出来,其实就是想说明电商的竞争非常激烈,极致的用户体验是分出胜负手的关键,这就是前端技术发挥余力的地方了。比如,尽快输出首屏幕的页面内容,尽快地让用户可以进行交互,等等吧。首页首屏秒开已经是电商的最低要求了,秒开,你懂吧?&br&&br&&b&那么,电商的首页首屏都有啥内容呢?如何以极限的速度呈现给用户呢?&/b&&br&&br&咱们是前端,我只能限制在前端的范畴。假设html文档都是150Kb左右,gzip之后是30Kb左右,网络带宽一样,而用户获得文档的时间基本是一致的。在这些前提下,我们同时获得文档之后,如何根据html结构布置js及其交互逻辑,才能以最快速度呈现首屏内容并提供交互呢?&br&&br&这里就以考拉网为例,其首屏内容如下图:&br&&figure&&img src=&https://pic4.zhimg.com/d00c43c8e96a60367ccf_b.png& data-rawwidth=&1440& data-rawheight=&900& class=&origin_image zh-lightbox-thumb& width=&1440& data-original=&https://pic4.zhimg.com/d00c43c8e96a60367ccf_r.png&&&/figure&&br&其首屏内容可细分为&br&&ol&&li&header部分(包括topbar、logo、搜索框和导航)&br&&/li&&li&slider广告幻灯片(多图)&br&&/li&&li&四个优势提醒(网易自营,低价保障,闪电发货,全场包邮)&br&&/li&&li&一个通栏广告(就是App下载的那个)&br&&/li&&/ol&由于浏览器线性加载的特点,首屏内容看到之前,我们至少会得到文档内容和css样式,如果我们第一时间让用户看到页面,那么,这里就应该只有首屏的图片就可以了,比如logo、购物侧图标、banner大图,四个优势对应的图标以及广告图片。&br&&br&如果我们将js布置在head里面,那么碰到js就要第一时间去加载js,这里就要消耗浏览器加载资源,对吗?而且js是阻塞方式加载的,即便是加载足够快,但也阻挡了首屏的内容!也就是,将js放在这里是不合适的。&br&&br&但是,我们将js放到文档的后面,如果前面有很多很多的图片资源,那么浏览器发起js加载请求可能就要等这些图片加载之后,那么首屏的页面却需要js提供交互了,比如幻灯片就是这种情况,那么首屏之后的内容就不能干扰js的加载,否则用户体验就很差,因为发生了TTI延迟问题(这个TTI兄弟,它有很多可以诉说的故事,切莫着急,俺会慢慢道来滴)。&br&&br&&b&事实上,网易考拉网的首页首屏内容的呈现的优化空间,至少有两点:&/b&&br&&br&&b&第1点:&/b&&br&&figure&&img src=&https://pic1.zhimg.com/5d3ee0961fca6fb6c18dec3c9d2a5f1c_b.jpg& data-rawwidth=&1125& data-rawheight=&475& class=&origin_image zh-lightbox-thumb& width=&1125& data-original=&https://pic1.zhimg.com/5d3ee0961fca6fb6c18dec3c9d2a5f1c_r.jpg&&&/figure&导航里面有很多“热卖大牌”,带有logo的,这些logo图片是直接用src发请求的,这是完全没有必要的,因为第一次进来用户没有触发导航下拉之前看不到这些东西,或者他可能从来到这里到离开,都不会点击打开下拉列表。&br&&br&比如我就是一个案例,在没有写这个文章之前,也不知道导航里面有那么多图片的,研究了源代码才发现这里还有那么多精彩,因此建议用js控制起来,用户没有触发之前就不要发起请求了。&br&&br&&b&第2点:&/b&&br&&figure&&img src=&https://pic3.zhimg.com/b3c1e9abc5c4da5fbd5dce_b.jpg& data-rawwidth=&1245& data-rawheight=&560& class=&origin_image zh-lightbox-thumb& width=&1245& data-original=&https://pic3.zhimg.com/b3c1e9abc5c4da5fbd5dce_r.jpg&&&/figure&首屏内容中轮播大图在用户进来之后就全部加载了,这也是没有必要的,只需要其中的一张即可。也就是,进入页面后用img的scr发起一个下载请求,其他img不要即刻去发起下载,而是等到js加载之后,用js来发起其他图片请求,等待所有轮播图片都加载完成之后,再执行轮播的逻辑。&br&&br&但是,如果要用js控制轮播图的加载就会有一个技术上的难点,如何知道轮播图片加载完成了呢?是全部完成之后再提供轮播切换交互,还是出现加载完一张就多一个切换,抑或是当加载到第n张之后就开始提供可交互,而不管n张以后的是否加载完成呢?此外,如果是要兼容IE6/7/8,坑很多。&br&&br&&b&按照这个思路,在兼顾SEO的前提下,&/b&&b&PC端&/b&&b&电商首页首屏要以极限的速度呈现给用户,我的做法是:&/b&&br&&ul&&li&&b&也就是说,&/b&&b&电商&/b&&b&网站&/b&&b&PC端做极限的性能优化,其精髓就是——&/b&&b&将浏览器基本无序的资源加载请求有序地控制起来,包括js本身,这就是js要放在脚步的缘由。&/b&&/li&&li&&b&除了首屏看得见的资源(主要是图片资源)外,其他资源一律需要通过js来控制,而不能随意地发起http请求&/b&&b&(包括首屏看不到的资源)&/b&&b&。按照这个原则,js只能放在body标签闭合之前,并且js逻辑不能随意书写!&/b&&/li&&/ul&其实这样做是有代价的,图片资源无法被搜索引擎正常抓取!但是这个对于电商来说,重要吗?大家都是要通过购买流量来PK的,所以不太重要。不同版本的浏览器下,对于资源下载都有一定优化,webkit内核的浏览器表现好很多,其他浏览器尤其是老版本的IE表现有时候让人搞不明。&br&&br&以考拉网为案例,说明电商网站喜欢将js放在底部,其缘由其实是因为业务优化需要,但并不是每一家都会这么做,典型的代表例如Tmall、VIP等,为什么有还是有不少电商是不放在底部的呢?&br&&br&其实很多时候还是要看业务需要,以及和一开始的技术选型有关,这个真不是一时半会可以说得清楚的,这里就不展开了。&br&&br&-----编辑于 09:12:23-----&br&&b&(三)逆向分析考拉网的前端架构方案&/b&&br&&br&这里分享的是根据别人将js放在底部,并且只能看到一大堆压缩优化后的代码,如何去学习别人前端架构设计的一种方法或途径。&br&&br&当然,我经常这么做,收获颇大,有时候想偷窥别人的源代码,这样才是最接近真实情况的,有时候确实也能瞎猫撞上死耗子。不管怎样,我觉得这种方法还是可行的,分享给大家。&br&&br&还是以考拉网为例。我先把首页html框架抽出来,梳理出大致页面结构,然后结合js,来看看别人是怎么做的。考拉的首页html框架如下:&br&&div class=&highlight&&&pre&&code class=&language-html&&&span class=&cp&&&!DOCTYPE HTML&&/span&
&span class=&nt&&&html&&/span&
&span class=&nt&&&head&&/span&
&span class=&nt&&&meta&/span& &span class=&na&&charset=&/span&&span class=&s&&&utf-8&&/span& &span class=&nt&&/&&/span&
&span class=&nt&&&title&&/span&网易考拉海购&span class=&nt&&&/title&&/span&
&span class=&nt&&&link&/span& &span class=&na&&rel=&/span&&span class=&s&&&stylesheet&&/span& &span class=&na&&href=&/span&&span class=&s&&&http://mm.bst.126.net/build/combo_f0ae46c.css?v=&&/span& &span class=&nt&&/&&/span&
&span class=&nt&&&link&/span& &span class=&na&&rel=&/span&&span class=&s&&&stylesheet&&/span& &span class=&na&&href=&/span&&span class=&s&&&http://mm.bst.126.net/build/combo_935bd74.css?v=&&/span& &span class=&nt&&/&&/span&
&span class=&nt&&&/head&&/span&
&span class=&nt&&&body&/span& &span class=&na&&class=&/span&&span class=&s&&&indexPage&&/span&&span class=&nt&&&&/span&
&span class=&nt&&&nav&/span& &span class=&na&&id=&/span&&span class=&s&&&topNav&&/span&&span class=&nt&&&&/nav&&/span&
&span class=&nt&&&h1&/span& &span class=&na&&class=&/span&&span class=&s&&&hide&&/span&&span class=&nt&&&&/span&网易考拉海购&span class=&nt&&&/h1&&/span&
&span class=&nt&&&header&/span& &span class=&na&&id=&/span&&span class=&s&&&docHead&&/span&&span class=&nt&&&&/header&&/span&
&span class=&nt&&&nav&/span& &span class=&na&&id=&/span&&span class=&s&&&topTabBox&&/span&&span class=&nt&&&&/nav&&/span&
&span class=&nt&&&div&/span& &span class=&na&&class=&/span&&span class=&s&&&wrap&&/span&&span class=&nt&&&&/span&
&span class=&nt&&&article&/span& &span class=&na&&class=&/span&&span class=&s&&&topBgWrap clearfix&&/span&&span class=&nt&&&&/span&
&span class=&c&&&!-- sliderBox --&&/span&
&span class=&nt&&&/article&&/span&
&span class=&nt&&&article&/span& &span class=&na&&class=&/span&&span class=&s&&&m-slogan&&/span&&span class=&nt&&&&/span&
&span class=&c&&&!-- 四个优势列表 --&&/span&
&span class=&nt&&&/article&&/span&
&span class=&nt&&&div&/span& &span class=&na&&class=&/span&&span class=&s&&&mainBgWrap clearfix&&/span&&span class=&nt&&&&/span&
&span class=&nt&&&article&/span& &span class=&na&&class=&/span&&span class=&s&&&m-recomds&&/span&&span class=&nt&&&&/span&
&span class=&c&&&!-- 每日上新列表 --&&/span&
&span class=&nt&&&/article&&/span&
&span class=&nt&&&article&/span& &span class=&na&&class=&/span&&span class=&s&&&m-halfbanner&&/span&&span class=&nt&&&&/span&
&span class=&c&&&!-- 四个半屏banner列表 --&&/span&
&span class=&nt&&&/article&&/span&
&span class=&nt&&&h2&/span& &span class=&na&&class=&/span&&span class=&s&&&w-tit1&&/span&&span class=&nt&&&&span&/span& &span class=&na&&class=&/span&&span class=&s&&&big&&/span&&span class=&nt&&&&/span&今日限时特卖&span class=&nt&&&/span&&/h2&&/span&
&span class=&nt&&&div&/span& &span class=&na&&id=&/span&&span class=&s&&&hotsaleblock&&/span&&span class=&nt&&&&/span&
&span class=&c&&&!-- 今日限时特卖列表 --&&/span&
&span class=&nt&&&/div&&/span&
&span class=&nt&&&article&/span& &span class=&na&&class=&/span&&span class=&s&&&m-recomds m-recomds-next&&/span&&span class=&nt&&&&/span&
&span class=&nt&&&h2&/span& &span class=&na&&class=&/span&&span class=&s&&&w-tit2&&/span&&span class=&nt&&&&span&/span& &span class=&na&&class=&/span&&span class=&s&&&big&&/span&&span class=&nt&&&&/span&下期特卖预告&span class=&nt&&&/span&&/h2&&/span&
&span class=&c&&&!-- 下期特卖预告列表 --&&/span&
&span class=&nt&&&/article&&/span&
&span class=&nt&&&h2&/span& &span class=&na&&class=&/span&&span class=&s&&&w-tit1&&/span&&span class=&nt&&&&span&/span& &span class=&na&&class=&/span&&span class=&s&&&big&&/span&&span class=&nt&&&&/span&全球精选&span class=&nt&&&/span&&/h2&&/span&
&span class=&nt&&&div&/span& &span class=&na&&class=&/span&&span class=&s&&&m-hslist clearfix&&/span&&span class=&nt&&&&/span&
&span class=&c&&&!-- 全球精选列表 --&&/span&
&span class=&nt&&&/div&&/span&
&span class=&nt&&&article&/span& &span class=&na&&class=&/span&&span class=&s&&&m-mustbuy&&/span&&span class=&nt&&&&/span&
&span class=&nt&&&h2&/span& &span class=&na&&class=&/span&&span class=&s&&&w-tit1&&/span&&span class=&nt&&&&span&/span& &span class=&na&&class=&/span&&span class=&s&&&big&&/span&&span class=&nt&&&&/span& 海淘必买 / &span class=&nt&&&/span&&/h2&&/span&
&span class=&c&&&!-- 海淘必买列表 --&&/span&
&span class=&nt&&&/article&&/span&
&span class=&nt&&&/div&&/span&
&span class=&nt&&&/div&&/span&
&span class=&nt&&&div&/span& &span class=&na&&id=&/span&&span class=&s&&&rightBar&&/span& &span class=&na&&class=&/span&&span class=&s&&&m-rightbar&&/span&&span class=&nt&&&&/span&
&span class=&c&&&!-- 左侧导航 --&&/span&
&span class=&c&&&!-- 这里语义有点问题,应该是右侧那条黑色Bar --&&/span&
&span class=&nt&&&/div&&/span&
&span class=&nt&&&footer&/span& &span class=&na&&id=&/span&&span class=&s&&&docFoot&&/span&&span class=&nt&&&&/span&
&span class=&c&&&!-- footer导航、版权区域 --&&/span&
&span class=&nt&&&/footer&&/span&
&span class=&nt&&&script &/span&&span class=&na&&src=&/span&&span class=&s&&&http://mm.bst.126.net/build/combo_a235696.js?v=&&/span&&span class=&nt&&&&/script&&/span&
&span class=&nt&&&script&&/span&
&span class=&c1&&//对导航效果进行初始化&/span&
&span class=&c1&&//这里为啥不判断 Core 是否存在呢?还不够严谨。&/span&
&span class=&nx&&Core&/span&&span class=&p&&.&/span&&span class=&nx&&navInit&/span&&span class=&p&&(&/span&&span class=&s2&&&http://mm.bst.126.net/&&/span&&span class=&p&&,&/span& &span class=&s2&&&&&/span&&span class=&p&&,&/span& &span class=&s2&&&&&/span&&span class=&p&&,&/span& &span class=&mi&&6&/span&&span class=&p&&,&/span& &span class=&kc&&true&/span&&span class=&p&&)&/span&
&span class=&nt&&&/script&&/span&
&span class=&nt&&&script &/span&&span class=&na&&src=&/span&&span class=&s&&&http://mm.bst.126.net/build/combo_ef4c658.js?v=&&/span&&span class=&nt&&&&/script&&/span&
&span class=&nt&&&script&&/span&
&span class=&c1&&//对导航效果进行初始化&/span&
&span class=&c1&&//这里的判断严谨多了&/span&
&span class=&c1&&//连续并列运算可简化判断,而且效率更高,请学习!&/span&
&span class=&nx&&Core&/span& &span class=&o&&&&&/span& &span class=&nx&&Core&/span&&span class=&p&&.&/span&&span class=&nx&&quickInit&/span& &span class=&o&&&&&/span& &span class=&nx&&Core&/span&&span class=&p&&.&/span&&span class=&nx&&quickInit&/span&&span class=&p&&();&/span&
&span class=&nt&&&/script&&/span&
&span class=&nt&&&script&&/span&
&span class=&c1&&//code here,省略&/span&
&span class=&nt&&&/script&&/span&
&span class=&nt&&&script &/span&&span class=&na&&src=&/span&&span class=&s&&&http://kxlogo.knet.cn/seallogo.dll?sn=e5000&size=0&&/span&&span class=&nt&&&&/script&&/span&
&span class=&nt&&&script &/span&&span class=&na&&src=&/span&&span class=&s&&&http://analytics.163.com/ntes.js&&/span& &span class=&na&&type=&/span&&span class=&s&&&text/javascript&&/span&&span class=&nt&&&&/script&&/span&
&span class=&nt&&&script &/span&&span class=&na&&type=&/span&&span class=&s&&&text/javascript&&/span&&span class=&nt&&&&/span&
&span class=&nx&&_ntes_nacc&/span& &span class=&o&&=&/span& &span class=&s2&&&kaola&&/span&&span class=&p&&;&/span& &span class=&c1&&//声明要统计的域&/span&
&span class=&nx&&neteaseTracker&/span&&span class=&p&&();&/span& &span class=&c1&&//网易自家的统计跟踪&/span&
&span class=&nx&&neteaseClickStat&/span&&span class=&p&&();&/span& &span class=&c1&&//网易自家对用户行文跟踪&/span&
&span class=&nt&&&/script&&/span&
&span class=&nt&&&script &/span&&span class=&na&&type=&/span&&span class=&s&&&text/javascript&&/span&&span class=&nt&&&&/span&
&span class=&c1&&//code here&/span&
&span class=&c1&&//这里还是一大堆第三方统计&/span&
&span class=&nt&&&/script&&/span&
&span class=&nt&&&/body&&/span&
&span class=&nt&&&/html&&/span&
&/code&&/pre&&/div&这份html结构可以膜拜一下,它在语义化方面做得非常出彩,几乎完美,特别是对H标签的使用非常合理,出神入化了,功力非常深厚,这种做法和163首页的做法如出一辙。可想而知,这一首页的html开发者应该系出同门,同样也可以想到网易内部的技术培训应该是完善的,建议大家好好观摩,值得学习。&br&&br&好了,神拜完了。我们开始吧。&b&第一个问题,网易考拉的js底层框架或类库是什么?&/b&&br&&br&咱们就从它的第一个js文件找找起,这就应该是他们的最基础的框架或类库,就这个 &a href=&//link.zhihu.com/?target=http%3A//mm.bst.126.net/build/combo_a235696.js& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&mm.bst.126.net/build/co&/span&&span class=&invisible&&mbo_a235696.js&/span&&span class=&ellipsis&&&/span&&/a&。&br&&br&大家不妨点击打开,然后格式化看看,工具比如&a href=&//link.zhihu.com/?target=http%3A//tool.oschina.net/codeformat/js& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&在线代码格式化&/a&,或者在Sublime text中安装一个格式化的插件,我用的是 &a href=&//link.zhihu.com/?target=https%3A//packagecontrol.io/packages/HTML-CSS-JS%2520Prettify& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&HTML-CSS-JS Prettify&/a& ,这个比较好用,其他编辑器没研究。格式化完成后,很容易找到 jquery: &1.4.2& 。就是这个了,底层是jquery-1.4.2版本,和官方的&a href=&//link.zhihu.com/?target=http%3A//code.jquery.com/jquery-1.4.2.js& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&code.jquery.com/jquery-&/span&&span class=&invisible&&1.4.2.js&/span&&span class=&ellipsis&&&/span&&/a&对比一下,没有改动。&br&&br&继续分解压缩后的代码,如下(跪求源码):&br&&div class=&highlight&&&pre&&code class=&language-text&&//jquery 1.4.2
!function(e, t) {
e.jQuery = e.$ = g
}(window);
//这里是一个二维码生成器基类,全局的
//学习点,QRCode定义在全局,但其实则放在一个闭包内部,避免污染
!function() {
QRCode = function(t, e) {
}, QRCode.prototype.makeCode = function(t) {
}, QRCode.prototype.makeImage = function() {
}, QRCode.prototype.clear = function() {
}, QRCode.CorrectLevel = l
//这里又是一个闭包,闭包内部主要是用来扩展jQuery的方法
//例如扩展Number/String原型方法、判断IE678、cookie等等
!function(e, t, i) {
//一大堆code
//这里有个有意思的东西,应该是一个弹窗
//不过是用Core.loadCdnJS异步加载的
t.dialog = t.dialog || function() {
Core.loadCdnJS(&js/dialog.js&, function() {
t.dialog.apply(t, e)
}(window, jQuery);
//这里就是页面上看到的自定义基类
var CopyCore = C
var Core = function(e, t, i) {
//一大堆code
}(window, jQuery);
jQuery(window).unload(function() {
//(⊙o⊙)…这里是让自定义基类Core在文档准备完成后初始化
jQuery(document).ready(function() {
Core.init()
//按语义,easyNav应该是一个快速导航的方法
var easyNav = function(e, t, i, n) {
//其实不用纠结是干什么的
//这里又是一个自运行的闭包
!function(e, t, i, n, o) {
//反正就是一大堆业务逻辑相关的代码
//其实不用纠结是干什么的
}(window, jQuery, Core, easyNav);
//这里又是一个自运行的闭包
!function() {
//这里里面好像是一些修复js原生方法缺陷的代码,比如json的处理
//其实不用纠结是干什么的
//这里定义了一个全局对象,带两个属性
this._nisas = {
_$host: location.host,
_$doc: document
//这里又是一个自运行的闭包
!function(e) {
//密密麻麻的不知道干什么,猜测是用来加密的,看得头晕眼花的
}(this._nisas);
//这里也还是一个自运行的闭包
!function(e, t, i) {
//autoSearch,也就是搜索时,输入关键词后自动联想的方法
}(window, jQuery);
//这里依然是一个自运行的闭包
!function(e, i, n) {
//目测就是一个弹出层登录注册业务空间
}(window, jQuery, easyNav);
&/code&&/pre&&/div&&br&----编辑于 12:54:22,继续偷窥----&br&这个文件 &a href=&//link.zhihu.com/?target=http%3A//mm.bst.126.net/build/combo_ef4c658.js& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&mm.bst.126.net/build/co&/span&&span class=&invisible&&mbo_ef4c658.js&/span&&span class=&ellipsis&&&/span&&/a&,内容就比较简单了,脉络如下:&br&&div class=&highlight&&&pre&&code class=&language-js&&&span class=&o&&!&/span& &span class=&kd&&function&/span&&span class=&p&&(&/span&&span class=&nx&&t&/span&&span class=&p&&,&/span& &span class=&nx&&e&/span&&span class=&p&&,&/span& &span class=&nx&&o&/span&&span class=&p&&,&/span& &span class=&nx&&i&/span&&span class=&p&&,&/span& &span class=&nx&&n&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&c1&&//一大堆业务逻辑,目测是全局的,比如用户状态处理、加入购物车等&/span&
&span class=&p&&}(&/span&&span class=&nb&&window&/span&&span class=&p&&,&/span& &span class=&nx&&jQuery&/span&&span class=&p&&,&/span& &span class=&nx&&Core&/span&&span class=&p&&,&/span& &span class=&nx&&easyNav&/span&&span class=&p&&);&/span&
&span class=&o&&!&/span& &span class=&kd&&function&/span&&span class=&p&&(&/span&&span class=&nx&&e&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&c1&&//easySlider,幻灯片逻辑,比较简单的,但做法值得借鉴&/span&
&span class=&c1&&//这可以学习一下,不知道是自己写的还是第三方库改的&/span&
&span class=&nx&&e&/span&&span class=&p&&.&/span&&span class=&nx&&fn&/span&&span class=&p&&.&/span&&span class=&nx&&easySlider&/span& &span class=&o&&=&/span& &span class=&kd&&function&/span&&span class=&p&&(&/span&&span class=&nx&&t&/span&&span class=&p&&)&/span& &span class=&p&&{}&/span&
&span class=&p&&}(&/span&&span class=&nx&&jQuery&/span&&span class=&p&&);&/span&
&span class=&o&&!&/span& &span class=&kd&&function&/span&&span class=&p&&(&/span&&span class=&nx&&e&/span&&span class=&p&&,&/span& &span class=&nx&&t&/span&&span class=&p&&,&/span& &span class=&nx&&a&/span&&span class=&p&&,&/span& &span class=&nx&&r&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&c1&&//也是一大堆业务逻辑,首页用到的 Core.quickInit 方法&/span&
&span class=&nx&&t&/span&&span class=&p&&.&/span&&span class=&nx&&extend&/span&&span class=&p&&(&/span&&span class=&nx&&a&/span&&span class=&p&&,&/span& &span class=&p&&{&/span&
&span class=&nx&&quickInit&/span&&span class=&o&&:&/span& &span class=&kd&&function&/span&&span class=&p&&()&/span& &span class=&p&&{&/span&
&span class=&c1&&//code&/span&
&span class=&p&&},&/span&
&span class=&c1&&//code&/span&
&span class=&nx&&myInit&/span&&span class=&o&&:&/span& &span class=&kd&&function&/span&&span class=&p&&()&/span& &span class=&p&&{&/span&
&span class=&c1&&//code&/span&
&span class=&p&&},&/span&
&span class=&p&&})&/span&
&span class=&p&&}(&/span&&span class=&nb&&window&/span&&span class=&p&&,&/span& &span class=&nx&&jQuery&/span&&span class=&p&&,&/span& &span class=&nx&&Core&/span&&span class=&p&&);&/span&
&span class=&o&&!&/span& &span class=&kd&&function&/span&&span class=&p&&(&/span&&span class=&nx&&e&/span&&span class=&p&&,&/span& &span class=&nx&&i&/span&&span class=&p&&,&/span& &span class=&nx&&o&/span&&span class=&p&&,&/span& &span class=&nx&&t&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&c1&&//签到,领取优惠券等逻辑&/span&
&span class=&nx&&i&/span&&span class=&p&&.&/span&&span class=&nx&&extend&/span&&span class=&p&&(&/span&&span class=&nx&&o&/span&&span class=&p&&,&/span& &span class=&p&&{&/span&
&span class=&nx&&yigouPop&/span&&span class=&o&&:&/span& &span class=&kd&&function&/span&&span class=&p&&()&/span& &span class=&p&&{&/span&
&span class=&c1&&//code&/span&
&span class=&p&&},&/span&
&span class=&nx&&getCoupon&/span&&span class=&o&&:&/span& &span class=&kd&&function&/span&&span class=&p&&(&/span&&span class=&nx&&e&/span&&span class=&p&&,&/span& &span class=&nx&&t&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&c1&&//code&/span&
&span class=&p&&},&/span&
&span class=&c1&&//code&/span&
&span class=&p&&})&/span&
&span class=&p&&}(&/span&&span class=&nb&&window&/span&&span class=&p&&,&/span& &span class=&nx&&jQuery&/span&&span class=&p&&,&/span& &span class=&nx&&Core&/span&&span class=&p&&);&/span&
&span class=&o&&!&/span& &span class=&kd&&function&/span&&span class=&p&&(&/span&&span class=&nx&&t&/span&&span class=&p&&,&/span& &span class=&nx&&e&/span&&span class=&p&&,&/span& &span class=&nx&&i&/span&&span class=&p&&,&/span& &span class=&nx&&n&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&nx&&e&/span&&span class=&p&&.&/span&&span class=&nx&&extend&/span&&span class=&p&&(&/span&&span class=&nx&&i&/span&&span class=&p&&,&/span& &span class=&p&&{&/span&
&span class=&nx&&checkIsNewer&/span&&span class=&o&&:&/span& &span class=&kd&&function&/span&&span class=&p&&()&/span& &span class=&p&&{&/span&
&span class=&c1&&//code&/span&
&span class=&p&&},&/span&
&span class=&nx&&initTemplates&/span&&span class=&o&&:&/span& &span class=&kd&&function&/span&&span class=&p&&()&/span& &span class=&p&&{&/span&
&span class=&c1&&//code&/span&
&span class=&p&&},&/span&
&span class=&c1&&//code&/span&
&span class=&p&&})&/span&
&span class=&p&&}(&/span&&span class=&nb&&window&/span&&span class=&p&&,&/span& &span class=&nx&&jQuery&/span&&span class=&p&&,&/span& &span class=&nx&&Core&/span&&span class=&p&&);&/span&
&/code&&/pre&&/div&到这里,我们基本得到了网易考拉的js业务框架模型,就是基于jQuery进行的扩展,然后定义名为‘ Core’的基类,后面均是继承这个基类来扩展业务,其实没有想象的那样复杂,反而非常简单。&br&&br&&b&简单就是高效,这是值得学习的,做架构就要将复杂的业务简单化。&/b&&br&&br&但问题是如何维护这样的代码?开发中肯定不是长成这样子的。团队配合开发,一定是分模块的,除非考拉只有一两个前端,这显然不合理嘛!如果要想得到这样的结果,并且容易维护,那么它的原来面目是怎样的呢?&br&&br&我画一个乱猜js目录结构示意图(重申,是乱猜的):&br&&figure&&img src=&https://pic2.zhimg.com/fcaafa4fe01f5e1bb89ba43dd5bed2c5_b.jpg& data-rawwidth=&1516& data-rawheight=&1095& class=&origin_image zh-lightbox-thumb& width=&1516& data-original=&https://pic2.zhimg.com/fcaafa4fe01f5e1bb89ba43dd5bed2c5_r.jpg&&&/figure&(请点击放大)&br&&br&在考拉的js源码里面,我们没有发现AMD或CMD的模块化身影,模块都是同步加载的,那么在开发中是如何调试呢?每一个js文件就写一个src请求吗?显然不合理。那么,他们是怎么做的呢?&br&&br&现在的前端本地都应该安装了nodejs环境了的,这是前提,那么能想方法有多:&br&&br&&b&方式1:&/b&&br&grunt直接本地combo,在开发状态下就如图所示,直接生成一份没有压缩的代码,比如core_debug.js,这个放置在某个地方,前端开发就直接构造URL,例如&br&&div class=&highlight&&&pre&&code class=&language-text&&&script src=&http://localhost:8080/build/core_debug.js&&&/script&
&script src=&http://localhost:8080/build/index_debug.js&&&/script&
&/code&&/pre&&/div&在开发状态下只需要弄一个grunt的任务监控,监控模块的变化,一旦有修改就马上生成新的,开发人员F5刷新一下页面就能看到页面了,或者开一个自动刷新页面的grunt任务。&br&&br&&b&方式2:&/b&&br&前端架构师写一个本地的在线combo服务器,服务器指向前端源码目录,然后让开发人员自己构造请求,然后combo服务器自动返回结果。类似这样:&br&&div class=&highlight&&&pre&&code class=&language-text&&&script src=&http://localhost:3333/??core/baseFn.js,core/core.js,core/core-init.js&&&/script&
&/code&&/pre&&/div&我以前写过名为‘一款淘宝风格的静态资源在线COMBO服务器’,有兴趣可以试试 &a href=&//link.zhihu.com/?target=http%3A//lmtdit.github.io/static-combo/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Static-combo&/a&,支持css和js。&br&&br&&b&方式3:&/b&&br&借助后端开发语言(一般就是php了,其实nodejs也可以),建立一个具备后端语言抽象能力的前端开发调试环境,然后弄一个js初始化的函数,比如写成这样:&br&&div class=&highlight&&&pre&&code class=&language-text&&&%- init_js('core/baseFn.js,core/core.js,core/core-init.js') %&
&/code&&/pre&&/div&输出的结果就如同上面的就可以了,这样的函数很容易实现的。其他语言版本也一样的。&br&&br&方法4、5、6、7、8……方法很多了,就不赘述了。&br&&br&开发好了之后,如何发版?如何解决由于内容摘要变化而引起的js引用路径变化的问题呢?这方面的原因和解析,可以参考FIS的做法,&br&&br&好了,这个问题基本到这里就超出了话题的范围。再深入,估计都没人再看了。&br&&br&&b&(四)之前的一些疑问解答&/b&&br&&b&&br&1,先针对VIP业务的几个问题&/b&&br&&br&&b&问题1:当我们要在页面中使用客户端渲染页面时,而渲染的模板结构代码直接书写在页面中,JS怎样布置才合理?&/b&&br&&br&很显然,由于模板是在页面中的,那么在这些代码之前最好将核心类库以及js模板引擎库放在它们的前面,就是这两段script代码。&br&&div class=&highlight&&&pre&&code class=&language-html&&&span class=&nt&&&script &/span&&span class=&na&&src=&/span&&span class=&s&&&//s2.vipstatic.com/js/public/jquery-1.10.2.js?&&/span& &span class=&na&&type=&/span&&span class=&s&&&text/javascript&&/span&&span class=&nt&&&&/script&&/span&
&span class=&nt&&&script &/span&&span class=&na&&src=&/span&&span class=&s&&&//s2.vipstatic.com/js/public/core3.js?&&/span& &span class=&na&&type=&/span&&span class=&s&&&text/javascript&&/span&&span class=&nt&&&&/script&&/span&
&/code&&/pre&&/div&看

我要回帖

更多关于 当是时也 的文章

 

随机推荐