1 、 浏览器界面渲染
浏览器是如何进行界面渲染的?
1. 解析HTTML,生成DOM树
2. 同时解析css, 生成样式规则(style rule)
3. 根据DOM树 和 样式规则, 生成渲染树(Render Tree)
4. 进行布局Layout(回流和重排):根据生成的渲染树,得到节点的几何信息(位置,大小)
5. 进行绘制Painting(重绘):根据计算和获取的信息进行整个页面的绘制
6. Display:展示在页面上
① 重绘
节点(元素)样式改变,但并不影响其在文档流的位置和文档布局,称为重绘
② 回流(重排)
当Render渲染树中的 部分或者全部元素 的 尺寸、结构、布局等发生改变时,浏览器重新渲染 部分或全部文档 的过程
比如:
- 页面首次刷新
- 浏览器窗口大小调整
- 元素大小/位置改变
- 内容变化(被逼入:input表单输入,图片大小)
- 激活css伪类
- 及脚本操作DOM(添加或删除可见的DOM元素)
结论:重绘不一定引起回流,但回流一定引起重绘;影响到布局了,就会有回流,仅仅只是像素值变化为重绘
2、BOM概述
BOM(Browser Object Model ):浏览器对象模型提供独立于内容而与浏览器窗口进行交互的对象,其核心对象是 window
BOM 由一系列相关的对象构成,并且每个对象都提供了很多方法与属性
BOM 缺乏标准,JavaScript 语法的标准化组织是 ECMA, DOM 的标准化组织是 W3C, BOM最初是Netscape 浏览器标准的一部分
DOM | BOM |
---|---|
文档对象模型 | 浏览器对象模型 |
DOM把文档当作 1个对象 看待 | 把浏览器 当作 1个对象看待 |
顶级对象document | 顶级对象window |
DOM主要学习操作页面元素 | 学习浏览器交互对象 |
DOM是W3C标准规范 | BOM各浏览器厂商自定义,兼容性较差 |
BOM的构成如上,BOM包含DOM
window对象是浏览器的顶级对象,具有双重角色:
- JS访问浏览器窗口的一个API接口
- window是一个全局对象,定义在全局作用域的变量、函数都会变成window对象的属性和方法
- 调用时可省略window
- 注意:window下的特殊属性window.name,所以不能给变量起名为name
3、window对象常见事件
① 窗口加载事件
window.onload
:是窗口(页面)加载事件,当文档内容完全加载完成会触发该事件(包括img、外联的css样式表、js等),就调用的处理函数。注意:- 有了
window.onload
就可以把JS代码写到页面元素的上方 - 因为
onload
是等页面内容全部加载完毕,再去执行事件处理程序,即加载JS代码 window.onload
传统事件注册方式同类型事件只能绑定1个事件处理程序,以最后1个为准
- 有了
document.addEventListener('DOMContentLoaded',function(){})
:仅当DOM加载完成,不包括img、css样式表、子框架等, 如果页面图片很多,从用户访问到onload触发可能需要较长时间,交互效果难以实现会影响用户体验,此时用DOMContentLoaded
事件比较合适,加载速度比load
更快一些load
事件监听整个页面资源给window
添加,DOMContentLoaded
给document
加,当初始的html文档被完全加载和解析完成后,DOMcontentLoaded事件被触发,而无需等待外联css、js、img完全加载
② 调整窗口大小事件
window.onresize
是调整窗口大小加载事件,只要窗口的大小发生像素变化,就会触发这个事件,常用于完成响应式布局window.innerWidth
当前屏幕的宽度
<body>
<script> //因为添加了onload,可以将JS代码放到HTML标签前面(任意位置)
window.addEventListener('load', function() {
var div = document.querySelector('div');
window.addEventListener('resize', function() {
console.log(window.innerWidth); //获取当前浏览器窗口大小
console.log('变化了');
if (window.innerWidth <= 800) { //响应式布局
div.style.display = 'none';
} else {
div.style.display = 'block';}})})
</script>
<div></div>
</body>
4、定时器
-
window.setTimeout(调用函数,[延迟的毫秒数]);
:该定时器在定时器到期后执行调用函数,window
可省; -
window.setInterval(回调函数,[间隔的毫秒数]);
:每隔 间隔时间就调用,第一次执行也是间隔毫秒数之后执行-
调用函数为匿名函数或写已经定义好的函数名
-
因为定时器可能有很多,所以经常给定时器赋值一个标识符
-
这个调用函数也称为回调函数 callback,普通函数按照代码顺序直接调用,而回调函数需要等待事件触发才会执行
-
-
window.clearTimeout(timeoutID)
:取消先前通过调用setTimeout()
建立的定时器 -
clearInterval ( )
方法取消了先前通过调用setInterval()
建立的定时器
this 的指向问题(this一定是指向对象的!!!)
this只有在函数执行时才能确定指向, 除了箭头函数, 在定义时this的指向就确定了
+ 全局作用域、普通函数中 this指向全局对象window
+ 方法调用中, 谁最近一级调用指向谁
+ 构造函数中,this指向构造函数实例
5、 JS执行机制
① JS是单线程
JS语言的一大特点就是单线程,即同一个时间只能做一件事。这是因为JS这门脚本语言诞生的目的 就是为处理页面中用户交互,以及操作DOM诞生的。比如对某个DOM元素进行添加和删除操作并不能同时进行。
单线程意味着,所有任务需要排队,前一个任务执行完毕,才会执行后一个任务。如果JS执行时间过长,会造成页面渲染并不连贯、加载阻塞之感
②同步和异步
为了解决这个问题,利用多核 CPU 的计算能力,HTML5 提出 Web Worker 标准,允许 JavaScript 脚本创建多个线程,于是JS出现同步和异步。
- 同步:前一个任务结束后,再执行下一个任务
- 异步:在做这件事同时,还可以处理其他事情
- 同步任务都在主线程上执行,形成一个
执行栈
- 异步任务是通过回调函数实现的,异步任务相关回调函数被添加到
任务队列
中,主要有 3 种类型:- 普通事件:click、resize等
- 资源加载:load、error等
- 定时器:setTtimeOut、setInterval等
执行步骤:
- 先执行 执行栈 中的同步任务
- 异步任务(回调函数)放到任务队列(消息队列)中
- 一旦执行栈中所有同步任务执行完毕,系统会按次序读取 任务队列 的异步任务,于是被读取的异步任务结束等待状态,进入执行栈,开始执行
总结:同步任务放在执行栈(主车道)中执行,异步任务由 异步进程处理 放入任务队列(应急车道)中,执行栈中的任务执行完毕会去 任务队列中查看是否有异步任务执行;由于主线程不断重复 获取任务、执行任务、再获取任务、执行任务,所以这种机制被称为 事件循环
6、 location对象
定义:window对象提供 location属性
用于 获取或设置窗体的URL,并且可以解析URL。由于 该属性返回值为一个对象,所以该属性也被称为location对象
,它拆分并保存了URL地址的各个组成部分
【案例:5s之后跳转页面 常用于应用软件打开是否跳过广告 .href assign()】
【案例:获取URL参数 实现URL参数在不同页面传递】
统一资源定位符(Uniform Resource Locator,URL)
统一资源定位符(Uniform Resource Locator,URL):互联网上标准资源的地址,互联网上每个文件都有 1个 唯一的URL,它包含的信息指出文件的位置 以及 浏览器应该如何处理它
protocol://host[:port]/path/[?query]#fragment
http://www.itcast.cn/index.html?name=andy&age=18#link
URL 组成 | 说明 |
---|---|
protocol | 通信协议 常用的http、ftp、maito等 |
host | 主机(域名) www.baidu.com |
port | 端口号,可选 |
path | 路径,由零或多个'/' 符号隔开的字符串 |
query | 参数,以键值对的形式,通过& 符号分隔开来 |
fragment | 片段, # 后面内容 常见于链接 锚点 |
location 对象属性 | 返回值 |
---|---|
location.href | 获取/设置整个URL【跳转页面】 |
.host | 主机(域名) |
.port | 端口号,未写返回空字符串 |
.pathname | 路径 |
location.search | 参数(获取表单提交数据,这也是为什么后续要学正则表达式的原因,爬虫) |
.hash | 获取地址中的哈希值,#后面内容常见于链接 锚点 |
案例:获取URL参数 实现表单数据在不同页面传递
首先:准备 2 个 html文件
//HTML <form> 元素表示文档中的一个区域,此区域包含交互控件,用于向 Web 服务器提交信息
//action处理表单提交的 URL 表单提交:index.html?uname=Andy
//method post 安全性更高数据包裹提交 get数据暴露在URL(爬虫就来了)
<form action="index.html" method="get"> //表单域
<label for="name">姓名:</label>
<input type="text" id="name" maxlength="4" name="uname"> //表单数据
</form>
<button>登录</button>
var uname = location.search.split('=').pop() //location.search = ?uname=Andy
var params = location.search.substr(1) //截取字符串 去掉?
var arr = params.split('=') //获得属性和属性值,因为有时候两个都需要
div.innerHTML = arr[1] + '主页欢迎您'
location方法 | 说明 |
---|---|
location.assgin() | 页面重定向,跳转页面,可以后退 记录浏览历史 |
location.replace() | 跳转页面,并不可以后退 |
location.reload() | 重新加载页面,相当于F5(还是有缓存),ctrl+F5强制刷新,完全重新打开 |
7、navigator对象
navigator
对象包含有关浏览器自身的相关信息,它具有很多属性,最常用的是userAgent
,该属性可以返回由客户端发送服务器的user-agent头部的值,即通过userAgent
检测浏览器的版本及平台
判断用户使用哪个终端打开页面,实现跳转
if((navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i))) {
window.location.href = ""; //手机
} else {
window.location.href = ""; //电脑
}
8、history对象
history
对象不包含用户(在浏览器窗口中)访问过的URL,可以与浏览器的历史极力进行交互
history对象方法 | 说明 |
---|---|
back() | 后退 |
forward() | 前进 |
go(参数) | 前进后退,前进+num个页面,后退-num个页面 |
9. 本地存储 (Web Storage)
随着互联网的快速发展,基于网页的应用越来越普遍,同时也变的越来越复杂,为了满足各种各样的需求,会经常性在 本地存储大量的数据,HTML5规范提出了相关解决方案。
- 数据以键值对的形式 存储在用户浏览器中
- 设置、读取方便、甚至刷新页面不丢失数据
- 容量较大、
sessionStorage
5M 和localStorage
约 20M - 只能存储字符串,无法存储复杂数据类型,可以将对象
JSON.stringify()
编码后, 再存储到本地,JSON.parse
(JSON字符串):将JSON字符串转换成对象 取出 时候使用 - 两者用法一致
存储数据:localStorage.setItem(key, value) //都是字符串,以键值对的形式存储、使用
获取数据:localStorage.getItem(key)
删除数据:localStorage.removeItem(key)
清除数据:localStorage.clear() //清除所有
① sessionStorage
- 声明周期为关闭浏览器窗口
- 在同一个窗口(页面)下数据可以共享
② localStorage
- 生命周期永久有效,除非手动删除,否则关闭页面也会存在
- 可以多窗口 / 页面 共享(同一浏览器可以共享)