### 你真的了解script标签吗?
先来看一个简单的html文档:
```html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Examples</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link href=".style.css" rel="stylesheet">
<script src="./app.js"></script>
</head>
<body>
<h1>hello Word</h1>
</body>
</html>
```
这是一份最简单不过的html文档了,我们只关注script标签,js的加载就可以了。
还有常见的这样的:
```
……
<script src="./jquery.js"></script>
<script src="./jquery.xxx.js"></script>
……
```
我们都知道依赖于jQuery的插件必须放在jQuery加载之后引入,否则会出错。
所以我们将插件加载的script标签写在后面,这样就不会出错了。
但是有一个问题,我们这样写真的能保证jQuery在之前加载吗,如果jQuery的cdn很慢呢,浏览器一定会保证加载顺序一定是按照我们写的顺序吗?以script标签的形式加载时浏览器是串行加载的吗?
是的,浏览器的确是保证加载顺序**按照我们写的script标签的顺序来依次加载并执行**(注意这里强调的**按照书写的script标签的顺序**,**依次加载并执行**),并且保证是串行加载的,所以我们这样写代码没有问题。所以如果cdn很慢,那么页面会一直卡在那里显示白屏,不会解析内容给用户,并且你可以尝试一下,在./app.js里面写一个死循环也是这样的,也就是说**浏览器是单进程执行js和加载js的,并且解析html和执行js也是单进程的,是阻塞的**,这种特性很多时候我们很容易感受到,比如弹窗时页面会“卡住”,加载时页面白屏等等,所以通常我们都建议不重要的js放在文档的最后body标签的前面就可以了,这样不会阻塞页面解析渲染。
(其实这里面浏览器有很复杂的细节,DOM书写顺序是执行顺序没错,但是加载是串行阻塞的还是并行的浏览器有自己的策略吧,这里面涉及的细节很复杂,不过可以肯定的是,DOM的顺序就表示了依赖关系,依赖的要写在上面,并且script的特性就是加载了就会执行里面的脚本,所以上面说加载并执行)
> 但为了不破坏您的页面渲染,我们还是建议您将涉及到javascript标签的代码,放到页面的最底部。
([百度分享](http://share.baidu.com/help/installation?type=icon)代码安装也是这样说明的)
为了简单,确保程序按照我们预期的运行,我们一直以来就是这样写script标签吗,并且它也是按照我们所想的运行,没有问题,但其实我们忽略了script标签的更多细节。
他还有两个很有用的参数,很多时候我们并没有使用过,甚至不知道。因为在我们的印象里面,浏览器按照写标签的顺序来依次加载,同时阻塞页面,这似乎是天经地义的,但其实有一些场景我们还是需要用到异步加载,异步执行的,这是就不会阻塞浏览器解析html给用户了,那么就不会显示白屏了,此时只会浏览器一直显示加载状态,但是页面已经呈现给用户了。
* * * * *
### 思考
**如何实现js非阻塞、并行加载,甚至能保持执行顺序呢?**
对于外部js我们的理解是“按照书写顺序依次加载并执行”(并且默认会阻塞浏览器的继续解析和渲染),虽然是这样的,但其实浏览器实际处理时不是这样的,不过我们平时这么说也没有错,但是最好还是要理解浏览器究竟是怎么做的。(如果依次/串行加载资源那效率太低了)
浏览器是可以并行加载资源的,而网络资源加载速度可能不同,那么如果是并行加载资源,就不可能是按顺序的加载完成了,那么浏览器是怎么保证“按顺序执行”呢?其实这里有一个机制,我们暂时称**X机制**,X机制能够保证浏览器最大效率的并行加载资源,但是资源加载完毕后并不立即被解析执行,而是被浏览器引擎“缓存”着了,直到最前依赖的加载完才会解析执行,比如同时加载1,2,3三个资源,2先返回,缓存着,3接着返回,继续缓存着,1返回,由于1是最前依赖,所以执行1,2已经返回了,直接执行,3同理,否则等待返回。也就是说,X机制在并行加载资源时,**保证JS执行顺序和书写顺序/依赖顺序一致,尽管它们的加载顺序不是一致的。** 即:浏览器要能够实现js非阻塞、并行加载,并且能保持执行顺序和书写顺序一致。
不过我们平常并不需要知道这个机制,这是浏览器内部的机制,**对我们来说,按照书写顺序依次加载并执行”这样说也是没错的,至少我们看到的代码就是这样运行的。**
~~~text
阮老师请教下,外部js的加载方式是:“按照书写顺序依次加载并执行”(并且默认会阻塞浏览器的继续解析和渲染),但其实浏览器并不是串行加载资源的,而是并行加载的(最大6个资源一起加载),如果是并行加载资源的,那么资源返回时间可能都不一样,那怎么保证加载完成按照顺序执行呢。这里面有些细节还不是很明白,不知道阮老师有没有写过类似的文章。谢谢。
不是“一起加载”,是“一起下载”。
(下载不等同于加载;下载:单纯的网络请求,文件下载。加载:包含下载和下载后的其它处理。)
~~~
> 或许这是我猜想的,对于普通的外部js,浏览器就是串行加载,依次加载并执行的。
[javascript在html中的加载顺序 - CBDoctor - 博客园](https://www.cnblogs.com/CBDoctor/p/3745246.html)
[浅析JavaScript执行顺序 « 邵珠庆の博客](http://shaozhuqing.com/?p=2756)
[Javascript 装载和执行 | | 酷 壳 - CoolShell](https://coolshell.cn/articles/9749.html)
> 对于IE来说,这个标签会让IE并行下载js文件,并且把其执行hold到了整个DOM装载完毕(DOMContentLoaded),多个defer的\<script\>在执行时也会按照其出现的顺序来运行。**(就是我上面说的X机制)**
[JavaScript并发下载 | 四火的唠叨](http://www.raychase.net/123)
[js的并行加载与顺序执行 - Hello.NET - 博客园](https://www.cnblogs.com/mfc-itblog/p/5938851.html)
[headjs实现网站并行加载但顺序执行JS_javascript技巧_脚本之家](http://www.jb51.net/article/98595.htm)
[js并行加载,顺序执行 - CSDN博客](http://blog.csdn.net/yemou_blog/article/details/50292339)
> 并行加载与顺序执行
[JS异步加载的三种方式 - CSDN博客](http://blog.csdn.net/l522703297/article/details/50754695)
[JS模块加载器加载原理是怎么样的? - 知乎](https://www.zhihu.com/question/21157540)
> 原理我用大白话告诉你,通过一个入口,加载所有依赖,每次完成一次onload,查看是否还有未完成和未开始的脚本,一直到最后一个加载完毕(加载过程是不阻塞的,当然也还是会分级)之后,按照依赖关系依次执行,结果保存到cache,下次再跑,就不执行了,确保factory只执行一次。
[浏览器加载 JS 文件的先后顺序同具体的解析和执行有什么关系? - 知乎](https://www.zhihu.com/question/20531965)
[前端 - 浏览器的并行加载机制是怎样的? - SegmentFault](https://segmentfault.com/q/1010000008784923)
* * * * *
[【requireJS源码学习03】细究requireJS的加载流程 - 叶小钗 - 博客园](https://www.cnblogs.com/yexiaochai/p/3650379.html)
> 执行checkLoaded方法,这里会开始递归的检查模块是否加载结束,一定要在主干模块depCount为0 时候才会执行其回调。(每次onload都检查就能知道是否全部加载完毕了)
[requireJS原理解析 - CSDN博客](http://blog.csdn.net/cde7070/article/details/65935888)
requireJS是通过动态创建\<script\>标签的方式加载资源的,这样虽然可以以 **异步不阻塞并行的方式加载文件** ,但是却无法保持执行顺序。不过也没事,每次完成一次onload就检查是否加载完全部依赖,等到全部加载完成后才执行回调,这样也是没问题的。但是对于不标准的AMD库,那就没办法了,毕竟标准的库都是define,factory在回调里面,所以即使加载完成也没有执行factory,但是非标准的就不同了,只要加载了就会立即执行,不知道对于这种情况是怎么处理的。(关于模块化怎么支持的可以看这里,[js.cookie.js](https://github.com/js-cookie/js-cookie/blob/master/src/js.cookie.js)、[layer.js](https://github.com/sentsin/layer/blob/master/src/layer.js))
估计对于非标准的AMD文件,requireJS不是采用的\<script\>标签的方式加载资源的吧。
由于requireJS的加载机制,并行加载,加载就执行脚本(脚本文件执行了而是factory),所以执行顺序是得不到保障的,保障的只是factory执行顺序和入口的回调。所以这里就有一个问题需要注意,**模块里面factory最好不要有单独直接部分,即使有,一定不要有依赖,否则就会出现依赖不存在的问题,所以一定要注意这点。**
* * * * *
### 扩展
试想一下如果某个cdn坏了,那么页面会一直显示加载白屏吗?
做个试验就知道了,其实浏览器都有一个超时时间,如果超时没有返回,那么会加载失败,浏览器就会放弃加载这个js,直接跳过了,如果之后的js依赖这个文件,那么就有可能会出问题了。
```
加载失败,报错:
GET http://h.qhimg.com/js/iwt.js net::ERR_CONNECTION_TIMED_OUT
```
至于css的加载,可以参考link标签,link标签没有这些复杂的其他参数,它就很简单,很单纯,那就是按标签书写顺序依次加载,并且同步阻塞的,所以页面重要样式一定要写在head里面,不然可能会出现用户看到一个坏的页面,然后突然又好了,所以样式一般都放在头部,这没有什么可说的,对于cdn坏掉还是跟js一样的,有一个超时时间,加载失败接。
不过要注意上面有一些表现在不同浏览器上面可能是不同的。
#### 名词解释:
**同步(sync),是串行,阻塞的**
**异步(Asynchronous ),是并行,非阻塞的**
> 这两组词往往都是成组出现的
## 参考
```
处理脚本和样式表的顺序
脚本
网络的模型是同步的。网页作者希望解析器遇到 <script> 标记时立即解析并执行脚本。文档的解析将停止,直到脚本执行完毕。如果脚本是外部的,那么解析过程会停止,直到从网络同步抓取资源完成后再继续。此模型已经使用了多年,也在 HTML4 和 HTML5 规范中进行了指定。作者也可以将脚本标注为“defer”,这样它就不会停止文档解析,而是等到解析结束才执行。HTML5 增加了一个选项,可将脚本标记为异步,以便由其他线程解析和执行。
预解析
Webkit 和 Firefox 都进行了这项优化。在执行脚本时,其他线程会解析文档的其余部分,找出并加载需要通过网络加载的其他资源。通过这种方式,资源可以在并行连接上加载,从而提高总体速度。请注意,预解析器不会修改 DOM 树,而是将这项工作交由主解析器处理;预解析器只会解析外部资源(例如外部脚本、样式表和图片)的引用。
样式表
另一方面,样式表有着不同的模型。理论上来说,应用样式表不会更改 DOM 树,因此似乎没有必要等待样式表并停止文档解析。但这涉及到一个问题,就是脚本在文档解析阶段会请求样式信息。如果当时还没有加载和解析样式,脚本就会获得错误的回复,这样显然会产生很多问题。这看上去是一个非典型案例,但事实上非常普遍。Firefox 在样式表加载和解析的过程中,会禁止所有脚本。而对于 Webkit 而言,仅当脚本尝试访问的样式属性可能受尚未加载的样式表影响时,它才会禁止该脚本。
```
- [前端文摘:深入解析浏览器的幕后工作原理 - 梦想天空(山边小溪) - 博客园](http://www.cnblogs.com/lhb25/p/how-browsers-work.html#Webkit_CSS_parser)
- [HTML <link> 标签](http://www.w3school.com.cn/tags/tag_link.asp)
- [HTML \<script\> 标签](http://www.w3school.com.cn/tags/tag_script.asp)
- [JavaScript 使用](http://www.w3school.com.cn/js/js_howto.asp)
- [深入浅出JavaScript (五) 详解Document.write()方法](http://blog.csdn.net/jiaolong724/article/details/8532828)
- [让我们再聊聊浏览器资源加载优化](http://kb.cnblogs.com/page/211942/)
- [浏览器允许的并发请求资源数是什么意思?](https://www.zhihu.com/question/20474326)
- [“不同浏览器对于同一域名的并发获取(加载)资源数是有限的” - 明明是悟空](http://www.tuicool.com/articles/maU7B3a)
- [详解浏览器最大并发连接数](http://www.iefans.net/liulanqi-zuida-bingfa-lianjieshu/)
- [现代浏览器的工作原理](http://blog.jobbole.com/12749/)
- [前端必读:浏览器内部工作原理](http://kb.cnblogs.com/page/129756/)
- [浏览器中Javascript的加载原理](http://blog.csdn.net/u012758088/article/details/54572673)
- [浏览器加载和渲染原理分析 ](http://blog.chinaunix.net/uid-24603373-id-220310.html)
- [html页面加载原理和浏览器应用程序交互原理](http://blog.csdn.net/ndcnb/article/details/51473667)
- [JS模块加载器加载原理是怎么样的?](https://www.zhihu.com/question/21157540)
- [关于浏览器处理新加入的JS,CSS方式原理](http://www.iteye.com/problems/7598)
- [JS \<script\>标签详解](http://www.itxueyuan.org/view/6611.html)
- [浏览器中JavaScript执行原理](http://www.cnblogs.com/inJS/p/4912843.html)
- [动态加载script文件的两种方法](http://www.jb51.net/article/40623.htm)
- [js在html中的加载执行顺序](http://www.cnblogs.com/lindaWei/archive/2012/04/05/2433454.html)
- [前端必读:浏览器内部工作原理](http://kb.cnblogs.com/page/129756/)
- [浅谈Html的内容加载及JS执行顺序](http://www.2cto.com/kf/201507/415672.html)
- [网站性能优化-将Script放到HTML文件中尽量靠近尾部原理](http://blog.csdn.net/spring21st/article/details/6192831)
- [浏览器加载、解析、渲染的过程](http://blog.csdn.net/xiaozhuxmen/article/details/52014901)
- [浏览器渲染页面过程](http://www.cnblogs.com/chenlogin/p/5221562.html)
- [浏览器~加载,解析,渲染](http://www.jianshu.com/p/e141d1543143)
- [浅析浏览器渲染页面过程](http://blog.csdn.net/yuhk231/article/details/53581212)
- [面试的时候人家问浏览器渲染过程 这个怎么答? ](https://zhidao.baidu.com/question/395315056469060285.html)
- [我的前端进阶学习(一)—— 模块化开发](http://www.imooc.com/m/wap/article/detail.html?aid=6911)
- [Javascript模块化编程(一):模块的写法](http://www.ruanyifeng.com/blog/2012/10/javascript_module.html)
- [Javascript模块化编程(二):AMD规范](http://www.ruanyifeng.com/blog/2012/10/asynchronous_module_definition.html)
- [Javascript模块化编程(三):require.js的用法](http://www.ruanyifeng.com/blog/2012/11/require_js.html)
- [浏览器加载 CommonJS 模块的原理与实现](http://www.ruanyifeng.com/blog/2015/05/commonjs-in-browser.html)
- [SeaJS 所为何](http://cyj.me/why-seajs/zh/)
- [RequireJS 其一](http://cyj.me/why-seajs/requirejs/)
- [JS模块化](http://www.kancloud.cn/xiak/quanduan/254621)
- [DNS 原理入门](http://www.ruanyifeng.com/blog/2016/06/dns.html)
- [浏览器工作原理(浏览器内核 即渲染)](http://blog.sina.com.cn/s/blog_6fb22e5b010117s0.html)
- [浏览器的工作原理:现代网络浏览器幕后揭秘](http://blog.sina.com.cn/s/blog_6deafdb2010146bt.html)
- [事件DOMContentLoaded和load的区别](http://www.jianshu.com/p/d851db5f2f30)
- [HTML 5 \<script\> async 属性](http://www.w3school.com.cn/tags/att_script_async.asp)
> 如果既不使用 async 也不使用 defer:**在浏览器继续解析页面之前,立即读取并执行脚本**
- [JS学习笔记(一)——JS的阻塞特性 - MeteorSeed - 博客园](http://www.cnblogs.com/MeteorSeed/articles/2283629.html)
> JS具有阻塞特性,当浏览器在执行js代码时,不能同时做其它事情,即\<script\>每次出现都会让页面等待脚本的解析和执行(不论JS是内嵌的还是外链的),JS代码执行完成后,才继续渲染页面。
- [现代浏览器性能优化-JS篇 · Issue #2 · GeoffZhu/geoffzhu.github.io](https://github.com/GeoffZhu/geoffzhu.github.io/issues/2)
- [现代浏览器性能优化-CSS篇 - 掘金](https://juejin.im/post/5a461f006fb9a0450408358f)
- [前端工程师必备——浏览器渲染原理详解!](https://www.toutiao.com/a6506267555328426499/?tt_from=weixin&utm_campaign=client_share×tamp=1514909819&app=news_article&utm_source=weixin&iid=22069500288&utm_medium=toutiao_android&wxshare_count=1)
### 其它
正因为“按照书写的script标签的顺序,依次加载并执行”,那么利用这个特性,可以实现,js脚本获取自身路径,[layer mobile](https://github.com/sentsin/layer/blob/2.x/src/mobile/layer.js)就是这么做的
里面有类似于这样的代码:
~~~javascript
var js = document.scripts, script = js[js.length - 1], jsPath = script.src;
var path = jsPath.substring(0, jsPath.lastIndexOf("/") + 1);
//如果合并方式,则需要单独引入layer.css
if(script.getAttribute('merge')) return;
document.head.appendChild(function(){
var link = doc.createElement('link');
link.href = path + 'need/layer.css?2.0';
link.type = 'text/css';
link.rel = 'styleSheet'
link.id = 'layermcss';
return link;
}());
~~~
关键是这个`document.scripts`,巧妙的利用了“一次加载并执行”。
那么问题来了,如果使用了模块化后,sea.js或者require.js这样的加载方式之后,那么势必就会改变这种情况,这种获取当前脚本路径的方式就不行了。
来看看,pc版的layer,也是这种方式。
好吧。
require.js其实没什么问题,sea.js就不行了,因为他是,尽可能的懒啊,尽可能的懒解析(执行),所以就会存在问题。
从layer的暴露模块支持代码就可以看出来,它不支持sea.js哦:
~~~javascript
//加载方式
window.layui && layui.define ? (
layer.ready()
,layui.define('jquery', function(exports){ //layui加载
layer.path = layui.cache.dir;
ready.run(layui.jquery);
//暴露模块
window.layer = layer;
exports('layer', layer);
})
) : (
(typeof define === 'function' && define.amd) ? define(['jquery'], function(){ //requirejs加载
ready.run(window.jQuery);
return layer;
}) : function(){ //普通script标签加载
ready.run(window.jQuery);
layer.ready();
}()
);
~~~
它支持三种方式:layui、require.js,普通script标签,唯独不支持sea.js,我们去社区看看sea.js支持方面的问题,果不奇然。
[layui.all 用sea js 载入会提示 css 路径不对的错误](https://fly.layui.com/jie/11504/)
[请问sea如何使用layer](http://fly.layui.com/jie/7458/)
> 不建议采用seajs
如果使用了sea.js那么需要自己配置脚本所在路径了,这种方式就行不通了。
[加快构建 DOM: 使用预解析, async, defer 以及 preload](http://mp.weixin.qq.com/s/CCjhMqiNNvjo-46FykN0UA)
> 在过去,为了执行一个脚本,HTML 的解析必须暂停。只有在 JavaScript 引擎执行完代码之后它才会重新开始解析。……
[Web图片资源的加载与渲染时机](https://segmentfault.com/a/1190000010032501?v=2017082201)
[前端性能优化之 DOM 篇 - 关人潮的博客 | FSUX Blog](http://fsux.me/%E9%9A%8F%E7%AC%94/%E6%9E%B6%E6%9E%84/%E6%B5%85%E8%B0%88%E5%89%8D%E7%AB%AF/2017/04/13/Front-end-performance-optimization-dom.html)
[从输入 URL 到页面加载完成的过程中都发生了什么事情?](http://fex.baidu.com/blog/2014/05/what-happen/)
[HTTP 缓存机制一二三 - 知乎专栏](https://zhuanlan.zhihu.com/p/29750583?group_id=901822939576557568)
[漫画揭秘一个超快的渲染引擎(上)](http://mp.weixin.qq.com/s/EAZUXq7RC6W9rWhRdE-7Ew)
[漫画揭秘一个超快的渲染引擎(下)](http://mp.weixin.qq.com/s/u8xUnB8nXWv_cvnVScAwoQ)
[前端开发工程师必须关注的几个性能指标](http://mp.weixin.qq.com/s/JV4yRQkkvsRxgwj3gw3zkQ)
[这么多前端优化点你都记得住吗?](http://mp.weixin.qq.com/s/QSakBZH5i_CfkPz4RHeFKg)
[如何打造一个全满分网站](http://mp.weixin.qq.com/s/NR_9y83sja-LjVzBs4viwA)
[如何打造一个安全满分网站](http://mp.weixin.qq.com/s/5CdnIN3eeAkux7rGJHjiyQ)
[浏览器「内核」都做了些什么?](https://mp.weixin.qq.com/s/JwUoIM2jcxbOd_5Mox4r-w)
[Webpack HMR 原理解析](http://mp.weixin.qq.com/s/eHFAYzX9GnxcixIjeMqojQ)
[Web静态资源缓存及优化](https://zhuanlan.zhihu.com/p/30780216)
[从Chrome源码看浏览器如何加载资源 – 人人网FED博客](https://fed.renren.com/2017/10/29/chrome-fetch-resource/)
[文字编码的那些事 – 人人网FED博客](https://fed.renren.com/2017/11/11/text-encode/)
[浏览器:一个家族的奋斗](http://mp.weixin.qq.com/s/5mOPs9Vcl0VNq4NAjdRPAg)
[火狐浏览器是如何又变快起来的?](https://mp.weixin.qq.com/s/ZTfqw_ECZCNqxifXGqfqwQ)
[【年底补课】HTTP缓存机制](https://mp.weixin.qq.com/s/HlJKEXk7q-f1n8va2RLZdA)
[曾是最强浏览器!Firefox是如何渐渐走向没落的_观点评论_太平洋电脑网PConline](http://pcedu.pconline.com.cn/938/9388346_all.html#content_page_2)
> 作为一个非营利性组织,Mozilla的目的是让浏览器市场多姿多彩,避免一家独大。Firefox一路走来,已经出色地诠释了这个使命。
[从输入网址到浏览器呈现页面内容,中间发生了什么?](http://mp.weixin.qq.com/s/q9wDvplWysHCn_Bet8j5lA)
[标准模式与怪异模式对渲染页面的影响](https://mp.weixin.qq.com/s/Y0l5YK68bi5A1KI2dhYf1w)
[浏览器家族的安全反击战](http://mp.weixin.qq.com/s?__biz=MzAxOTc0NzExNg==&mid=2665514143&idx=1&sn=28ea209c00309e6b93d8d1f76032d7a4&chksm=80d67cdcb7a1f5ca81d8d454a98af56d58b22f6058f100e21ff30e70867ea6e3e922a4f000bf&scene=21#wechat_redirect)
> 同源 & 安全:这些安全策略都是浏览器制定的,假如浏览器也不安全,我电脑的浏览器被黑客攻击了,那么怎么办?
>
> 没辙了,你的核心被攻占, 除非你把浏览器或者OS重装了
[HTML 文档之 Head 最佳实践](https://mp.weixin.qq.com/s/GF3HPhFrXll6eEI8crJCaw)
[谈谈web前端缓存](https://www.toutiao.com/a6505280890388611597/?tt_from=weixin&utm_campaign=client_share×tamp=1514707129&app=news_article&utm_source=weixin&iid=22069500288&utm_medium=toutiao_android&wxshare_count=1)
[浅谈浏览器 http 的缓存机制](https://mp.weixin.qq.com/s/qSN5yaNmuMysG71229qC-Q)
[让我们再聊聊浏览器资源加载优化 – 前端技术漫游指南](http://qingbob.com/let-us-talk-about-resource-load/)
[Range/Content-Range与断点续传,了解一下? - 掘金](https://juejin.im/post/5acac9f5f265da239531463f)
[web beacon - jvava - 博客园](https://www.cnblogs.com/jvava/p/3926539.html)
* * * * *
last update:2018-1-22 22:09:31
- 开始
- 微信小程序
- 获取用户信息
- 记录
- HTML
- HTML5
- 文档根节点
- 你真的了解script标签吗?
- 文档结构
- 已经落后的技术
- form表单
- html实体
- CSS
- css优先级 & 设计模式
- 如何编写高效的 CSS 选择符
- 笔记
- 小计
- flex布局
- 细节体验
- Flex
- Grid
- tailwindcss
- JavaScript
- javascript物语
- js函数定义
- js中的数组对象
- js的json解析
- js中数组的操作
- js事件冒泡
- js中的判断
- js语句声明会提前
- cookie操作
- 关于javascript你要知道的
- 关于innerHTML的试验
- js引擎与GUI引擎是互斥的
- 如何安全的修改对象
- 当渲染引擎遇上强迫症
- 不要使用连相等
- 修改数组-对象
- 算法-函数
- 事件探析
- 事件循环
- js事件循环中的上下文和作用域的经典问题
- Promise
- 最佳实践
- 页面遮罩加载效果
- 网站静态文件之思考
- 图片加载问题
- 路由及转场解决方案
- web app
- 写一个页面路由转场的管理工具
- 谈编程
- 技术/思想的斗争
- 前端技术选型分析
- 我想放点html模板代码
- 开发自适应网页
- 后台前端项目的开发
- 网站PC版和移动版的模板方案
- 前后端分离
- 淘宝前后端分离
- 前后端分离的思考与实践(一)
- 前后端分离的思考与实践(二)
- 前后端分离的思考与实践(三)
- 前后端分离的思考与实践(四)
- 前后端分离的思考与实践(五)
- 前后端分离的思考与实践(六)
- 动画
- 开发小技巧
- Axios
- 屏幕适配
- 理论基础
- 思考
- flexible.js原理
- 实验
- rem的坑,为什么要设置成百分比,为什么又是62.5%
- 为什么以一个标准适配的,其它宽度也能同等适配
- 自适应、响应式、弹性布局、屏幕适配
- 适配:都用百分比?
- 番外篇
- 给你看看0.5px长什么样?
- 用事实证明viewport scale缩放不会改变rem元素的大小
- 为什么PC端页面缩放不会影响rem元素
- 究竟以哪个为设备独立像素
- PC到移动端初试
- 深入理解px
- 响应式之栅格系统
- 深入理解px(二)
- 一篇搞定移动端适配
- flex版栅格布局
- 其他
- 浏览器加载初探
- 警惕你的开发工具
- JS模块化
- webpack
- 打包原理
- 异步加载
- gulp
- 命名规范
- 接口开发
- sea.js学习
- require.js学习
- react学习
- react笔记
- vue学习
- vue3
- 工具、技巧
- 临时笔记
- 怎么维护好开源项目
- 待办
- 对前端MVV*C框架的思考
- jquery问题
- 临时
- 好文
- 节流防抖