标签存档: JS

兵贵神速-domReady事件原理及相应jQuery源码分析

突然发现,其实本来自以为非常熟悉的一些技术,一旦被人提问以后就会发现自己并不能很好地说明清楚,所以开始认真地写一些非常基础的技术分享,不断查资料探究原理的过程还是非常有趣的

2009090812124856310.jpg

之前被问domReady事件到底是啥,比onload到底好在哪里,一句话说的话就是 DomTree加载完成之后,不等图片加载完domReady就会发生,这时绝大多数JS已经可以正常地运行了(因为页面上初始的dom元素都齐了)。但要说清楚这个domReady的来龙去脉,还真没那么简单。

W3C标准页面加载过程

W3C中关于浏览器加载过程的时间信息的接口标准中有很多页面加载方面的标准,简单地说在chrome里检查performance.timing就可以看见各个事件发生的时间戳
無名の QQ スクリーンショット.png
W3C的这张图很好地描述了浏览器加载页面的整个过程,除了domLoading(开始解析dom树)可能会抢先在responseEnd(网络接受应答完毕)之前发生之外,基本是从左到右时间顺序发生

这里我们关注processing以及之后的部分,我尝试解释一下各个事件的含义

  • domLoading 浏览器拿到了一些HTML代码,开始解析dom树
    • 设置document.readyState为”loading”(也就触发了readyStateChange)
    • 注意引用的外部script会阻塞dom树解析
    • 解析过程比较复杂这里不多涉及,可以参考W3C的Parsing部分的标准
  • domInteractive 浏览器初步解析完dom树,但并不稳定,仍残余一些工作,W3C的相关标准链接
    • 设置document.readyState为”interactive”
    • 清空打开标签堆栈,也就是强制关闭仍未闭合的标签
    • 写在html中的script元素,含defer属性且不含async属性的会在这个时机被执行
    • 此时才会触发domContentLoaded事件
  • domContentLoaded其实就是俗称的domReady事件,此时dom树已经稳定
    • aync属性的script元素在这个时机被执行
    • 满足另一种条件的script元素也是这个时机被执行,我没能看懂,估计是来自于document.createElement创建出来的某种情况
  • domComplete 需要加载的资源(包括图片、iFrame等等等等)以及脚本全部执行完毕
    • 设置document.readyState为”complete”
    • 这个事件和load事件的区别是load事件必须要有Browsing Context才会被触发,但时机是一样的
  • loadEventStart load事件被触发
  • loadEventEnd load事件执行完毕

domReady的现实

一般来说我们希望页面上的脚本尽量快速地被执行,但很多情景下都需要完整可操作的dom树才能保证脚本执行正确,尤其是IE6在interactive以及之前的阶段,如果用JS操作了dom树会直接“无法打开站点”。

问题是绝大多数情况下,图片(或者swf等)都不是JS脚本需要的资源,也就是说我们要找的时间点是dom树完整之后,图片加载之前的一个地方来执行我们的脚本,也就是所谓的domReady。对于主流标准浏览器来说,domContentLoaded正是我们需要的domReady,但很不幸我们生活在有IE的世界里,所以需要为IE找一个替代品(doScroll checking)

jQuery相关源码解析

这里看的是jQuery1.7.2的代码,相关部分在core.js里面

jQuery里domReady的绑定代码是jQuery(callback)或者jQuery(document).ready(callback),最终都落到了jQuery.fn.ready上,readyList维护注册在ready时间上的callback集合,jQuery.ready是jQuery希望绑定在domReady上的callback,里面会执行所有通过各种手段绑定上ready的callback,于是我们主要看jQuery.bindReady

  1. 处理了被调用时已经load事件都发生过的情况(L430)
  2. 对标准浏览器,用domContentLoaded事件并同时也绑上load事件作为fallback来支持早期版本 (L437)
  3. 对IE,首先绑定了readystatechange的complete的情况,以及load事件,然后尝试使用doScrollCheck来更早地触发ready事件(L445)

domReady的问题

domReady虽然通常比load快不少,但此时并不能保证外部资源全部load到,所以需要读img/包含img的元素的尺寸时不能直接在domReady里面跑,flash及类似的外部资源也有类似的问题


参考:DOM Ready 详解

Permanent link to this article: http://mcfog.com/p848/%e5%85%b5%e8%b4%b5%e7%a5%9e%e9%80%9f-domready%e4%ba%8b%e4%bb%b6%e5%8e%9f%e7%90%86%e5%8f%8a%e7%9b%b8%e5%ba%94jquery%e6%ba%90%e7%a0%81%e5%88%86%e6%9e%90.fog

【原创】在线生成器 of 《魔法少女小圆》剧中的符文

我又蛋疼了……点击进入在线生成器

好吧,剧中的符文中还缺X等个别字母,不过本站的域名倒是够了

http://McFog.com

TTF格式字体来自此维基页

Permanent link to this article: http://mcfog.com/p699/%e3%80%90%e5%8e%9f%e5%88%9b%e3%80%91%e5%9c%a8%e7%ba%bf%e7%94%9f%e6%88%90%e5%99%a8-of-%e3%80%8a%e9%ad%94%e6%b3%95%e5%b0%91%e5%a5%b3%e5%b0%8f%e5%9c%86%e3%80%8b%e5%89%a7%e4%b8%ad%e7%9a%84%e7%ac%a6.fog

真·SWF图片幻灯(JS-ActionScript通信)

图片幻灯是一个异常古老而经典的Flash应用,然而实际应用时发现网上找的多数幻灯效果都停留在上个世纪的水平,所谓的JS+SWF不过是document.write罢了

正好在项目里要用图片幻灯,也思考了一下,Flash的唯一长处在于显示图片切换效果的时候更加流畅、自然,但在灵活性上输JS无数条大街,于是自己动手写了个SWF图片幻灯,非常简单,对外接口只有2个:一个JS回调方法loadImage(url),载入url指向的图片,可选的用flashvar传递的初始图片

此SWF就做一件事:收到loadImage(或者flashvar的初值)的时候,显示一个ajax loading的gif,然后去读图片,图片读到以后随机一种效果显示出来覆盖掉原来的图片 文字说明啊,定时切换啊什么的这些功能就扔给JS来实现了,用jQuery的话都是优雅地数行代码轻松搞定的问题(tips:如果需要和点击互动,请自行在flash上罩一层DIV即可)

演示地址: http://p.mcfog.com/mcfocus/ SWF文件请自抠

推荐配合jQuery以及jquery.swfobject

Permanent link to this article: http://mcfog.com/p676/%e7%9c%9f%c2%b7swf%e5%9b%be%e7%89%87%e5%b9%bb%e7%81%afjs-actionscript%e9%80%9a%e4%bf%a1.fog

userscript开发笔记:contentEval解决访问全局JS变量/资源问题

嗯,整了一个userscript 玩玩,过程中发现UserScript访问页面中定义的JS变量(比如说jQuery的美刀$) 在不同环境(FF+GreaseMonkey/Chrome原生/Chrome+不同的userscript管理扩展)下有各种稀奇古怪的问题,FF的GreaseMonkey里的unsafeWindow丑陋又不靠谱,Chrome原生干脆不支持unsafeWindow,Chrome的一些插件尝试了支持unsafeWindow但即不靠谱,还要多装一个东西……
搜索了一下找到一个很好的解决方案,在这里记录一下
继续阅读 »

Permanent link to this article: http://mcfog.com/p665/userscript%e5%bc%80%e5%8f%91%e7%ac%94%e8%ae%b0%ef%bc%9acontenteval%e8%a7%a3%e5%86%b3%e8%ae%bf%e9%97%ae%e5%85%a8%e5%b1%80js%e5%8f%98%e9%87%8f%e8%b5%84%e6%ba%90%e9%97%ae%e9%a2%98.fog

javascript的ajax编程中setTimeout的妙用-0毫秒之后执行

setTimeout通常用于动画/计时等应用,但是不加第二个时间参数或者写0或1毫秒也是非常有用的,有时需要让某段代码“略微延后”执行以等待之后的代码(例如函数调用者的后续代码,以及后续事件的代码)

我把最近用setTimeout解决的一个问题举例一下,需求是这样的:先用ajax(1)打开一个浮动层“对话框”,内容由ajax(1)获取,其中含有另外一个表单,在对话框中提交以完成某操作ajax(2),需要在提交完成以后自动关闭那个对话框并执行第三个ajax(3)操作(刷新页面数据)

基于代码复用,灵活性等的角度考虑,我希望打开对话框的这个function能够接受关闭时的动作为参数(这里是执行ajax(3)),以及接受是否自动关闭对话框也作为参数

整个过程在jQuery和jQueryUI下完成,例子中我去掉了jQueryUI,因为此处jQueryUI仅仅负责渲染对话框,另外例子里面省略了第三个ajax,仅以输出信息示意

点击这里查看范例
继续阅读 »

Permanent link to this article: http://mcfog.com/p595/settimeout-in-javascript-ajax.fog

JS动态载入jQuery并在jQ的环境下执行代码

嗯,很绕口的标题,这段代码源于这样一种需求:在类似『JS调用』的应用中需要确保一些JS在jQ的环境下执行,但通常的<script>包含jQ会让js调用代码变成2个<script>,且如果目标页面已经载入了jQ的情况下将导致资源浪费。
这段代码会检测当前JS是否已经有了jQ环境(标准的$形式),如果没有,动态载入jQuery(从googleapi处)、等待加载完毕再执行main回调,如果已经有了jQ环境,直接执行main回调
原谅我把代码放到Continue Reading……
继续阅读 »

Permanent link to this article: http://mcfog.com/p210/js-and-jquery-dynamic-loading-environment-to-execute-code-jq.fog

みくみくにしてあげる♪
初音