客户端web应用的两个生命周期阶段
构建阶段
浏览器根据html生成dom树,根据css生成css规则树。确定页面元素位置的过程称为回流,确定页面元素自身内部样式的过程称为重绘。回流涉及元素自身及其“周围”元素的位置确定,重绘只涉及元素自身的表现,因此,回流的成本高于重绘。
渲染完毕后,浏览器开始解析并执行js文件,这个过程中就有可能触发回流和重绘。等到全局JS完全执行完毕,页面“真正”确定下来,接下来就等待用户交互。事件循环阶段
JS引擎会维护一个事件队列,不断检查队首是否有事件需要执行。其逻辑类似如下代码:
while (true) {
var eventHandler = eventHandlerQueue.pop()
eventHandler()
}
事件来源可以是用户操作,比如点击按钮,为UI添加事件监听的方式如下:
// 事件目标对象的 addEventListener 方法
eventTarget.addEventListener('eventName',function handler(){})
// dom元素的事件属性
eventTarget.onclick = function handler(){}
<button onclick='clickHander()'>click</button>
或者我们可以自定义事件:
// 创建事件目标对象,并为 customEvent 添加一个监听器
var eventTarget = new EventTarget()
eventTarget.addEventListener('customEvent', function handler(){})
// 创建一个事件对象,在事件目标对象上分发一个 customEvent 事件
var event = new Event('customEvent', { value: 'foo' })
eventTarget.dispatchEvent('customEvent')
也可以是服务器响应:
var xhr = new XMLHttpRequest()
xhr.open(method, url)
xhr.onreadystatechange = function handler() {}
xhr.send()
当事件触发之后,引擎就会往事件队列队尾添加一个回调函数。
eventQueue.put(handler)
当回调函数到达队首,则会被执行。基于以上的逻辑,触发事件仅仅是把回调函数放到事件循环队列,事件执行需要等到该回调函数出队。