浏览器对象模型(Browser Object Model) / BOM
BOM是由一系列相关对象构成,每个对象都提供了很多方法和属性。
在 BOM 里最重要的对象有 5 个, 分别如下:
- window (窗口):window 是整个网页的框架,每个网页的内容都是装载在 window 里面
- navigator (浏览器):navigator 里面存储浏览器相关信息
- history (历史):我们知道每个网页可以前进后退,history 便拿来存储整个网页栈的
- screen (显示屏幕):screen 包含我们显示屏幕的信息,这个是硬件信息
- location (地址):location 包含当前访问的地址(网址)信息
- screen 是 整个电脑 唯一的
- navigator 是 整个浏览器 唯一的,如果有多个浏览器就会有多个 navigator
- window 是 每个网页 唯一的,每个网页都有一个独立的 window
- history,location 是 每个网页 的信息,当然也是网页唯一的
HTML 中嵌入 Javascript
window
- window 对象表示一个浏览器窗口或一个 frame 框架,它处于对象层次的最顶端,它提供了处理浏览器窗口的方法和属性。
- window 对象是浏览器对象中的默认对象,所以可以隐式地引用 window 对象的属性和方法。在浏览器环境中,添加到 window 对象中的方法、属性等,其作用域都是全局的。
Location/History
location其用来保存当前网页位置的信息。
Location 方法
--- reload() 方法
为了防止无限快速循环,我们设置一个定时器延迟调用 reload。
location.reload()
方法用来刷新当前页面,就像刷新按钮一样。
setTimeout(function () {
window.location.reload();
}, 3000);
跳转到新的地址
直接将网页地址赋值给 Location
可以直接修改location的值。
window.location = 'https://www.youkeda.com';
History
History 允许操作浏览器的曾经在标签页或者框架里访问的会话历史记录,由这个名称我们得知,History 会存储该窗口的历史记录。
在实际存储中用到的数据结构和数组特别类似,叫做栈。
History中方法
back() 和 forward() ,分别对应到浏览器左上角的返回和前进按钮。
Navigator/Screen
Navigator 表示用户代理的状态和标识,也就是浏览器基本信息,在这里面我们需要了解一个属性 --- userAgent,代表当前浏览器的用户代理。
DOM
文档对象模型 (DOM) 可以将 web 页面 与 脚本或编程语言 连接起来.
重点
1. web 页面
这里的 web 页面,也就是之前我们用 HTML 和 CSS 绘制的页面,也称作为文档
2. 脚本或编程语言 为什么这里不直接说将 Web 页面和 Javascript 语言连接起来,而要绕一下说脚本或编程语言呢?
因为 DOM 是一种规范 ,或者是一种约定 ,只要遵循这个规范,那么无论是
Javascript
,还是python
,或者java
都可以被连接起来。
访问DOM
获取DOCUENT
web 网页最终会映射为一棵 DOM 树,DOM 树连接网页和 Javascript 语言。
DOCUMENT 元素会存在全局变量 window 下面,可以直接访问:
window.document;
选择器查询
选择器查询方法 --- querySelector()
//基础筛选条件
'.subtitle';
//加强版本,加上父亲筛选, 筛选 main标签下面 -> class为core的节点下面 -> class为subtitle的节点
'main .core .subtitle';
document.querySelector('main .core .subtitle');
迭代查询
当我们得到 subtitle 元素后,我们还可以利用这个元素,继续筛选器内部元素,比如我们想筛选器内部的 a 标签。
let subtitle = document.querySelector('main .core .subtitle');
console.log(subtitle.querySelector('a'));
选择器全量查询
查询上面 HTML 中的所有 input 节点.
document.querySelectorAll('input');
查询返回的是一个类数组,我们可以直接通过索引访问。
类数组,顾名思义类似数组形式,(可以通过索引访问的对象我们都可以称之为类数组),从 JSConsole 中我们实际得到的是NodeList对象。
getElementById() : 根据 id 查询某个节点
getElementsByClassName() : 根据 class 查询多个节点
getElementsByTagName() : 根据 标签名 查询多个节点
querySelector 查询出来的元素是拷贝的原始数据,不会再随着页面 DOM 节点的改变而变化 get 系列方法 查询出来的元素就是原始数据,所以会随着页面的 DOM 节点的改变而变化
DOM属性
DOM种类
<!-- HTMLDocument 根文档 -->
<html>
......
</html>
<!-- HTMLDivElement DIV类型 -->
<div class="subtitle">
......
</div>
<!-- HTMLAnchorElement 超链接类型 -->
<a class="free-bright">免费靓号</a>
<!-- HTMLInputElement Input类型 -->
<input class="password" type="pasworkd" placeholder="请输入密码" />
DOM的类别
-
元素节点
-
特性节点
-
文本节点
-
...... 其他类别不重要。
-
整个 HTML 中,无论是标签,标签属性,还是纯文本字符串都是
Element
, 不同的地方在于nodeType
分别为1, 2, 3
。 -
HTML 标签都是元素节点 ,可以用
nodeName
获取标签名称 -
纯文本都是文本节点 ,可以用
nodeValue
获取文本内容 -
标签的每个属性都是特性节点 ,可以用
nodeName
取得属性 Key,用nodeValue
取得属性 Value -
attributes
可以获取元素节点的所有属性,得到的结果是一个字典,通过属性 Key 获取对应的特性节点。
DOM内容
属性 | 总结 | |
---|---|---|
outerHTML | 整个 DOM 的 HTML 代码 | |
innerHTML | DOM 内部 HTML 代码 | |
innerText | DOM 内部纯文本内容 |
DOM亲属
let divDom = document.querySelector('div#test');
console.log(divDom.firstChild, divDom.lastChild);
console.log('-----');
console.log(divDom.childNodes);
console.log('-----');
console.log(divDom.parentNode);
属性 | 值 | 总结 |
---|---|---|
firstChild | 指定节点的第一个子节点 | |
lastChild | 指定节点的最后一个子节点 | |
childNodes | 指定节点的子节点的集合 | |
parentNode | 指定节点在 DOM 树中的父节点 |
lastChild 的值为 text
实际上就是换行符。
DOM样式
属性 | 类型 | 值 | 总结 |
---|---|---|---|
classList | DOMTokenList 类数组 |
['test'] |
classList 数组方式存储所有的 class 名称 |
style | CSSStyleDeclaration |
color 属性为rgb(255, 51, 0) |
对象或字典的方法存储 CSSStyle |
DOM数据属性
HTML 提供一种数据属性的标准,利用data-*
允许我们在标准内于 HTML 元素中存储额外的信息。
有一些数据,,不一定是直接展示的,有可能字数是某种特效才展示,分类数据是动态更新时需要用到,可以利用data-*
来存储。
<article data-parts="3" data-words="1314" data-category="python"></article>
数据的获取:
const article = document.querySelector('article');
console.log(article.dataset);
dataset
是个 Map 对象,它是data-*
这个*
的Key-Value集合。
DOM操作
1. 创建标签节点
document.createElement(tagName)
此方法用于创建一个由标签名称 tagName 指定的 HTML 元素,也就是上节课提到的元素(标签)节点。
如果想创建一个div
标签,我们可以使用:
const div = document.createElement('div');
创建文本方法**document.createTextNode(),
这个div
标签内部,添加纯文本内容
把txt
添加到div
中,把div
添加到body
中
const div = document.createElement('div');
const txt = document.createTextNode('优课达-学的比别人好一点');
div.appendChild(txt);
document.body.appendChild(div);
2. 添加新节点
appendChild(newNode)
inserBefore(newNode, referenceNode)
此方法和appendChild()
刚好相反,appendChild
是在所有儿子节点之后 添加,inserBefore
是在某个目标儿子节点之前添加。
insertBefore(newNode, referenceNode)
,需要两个参数,newNode
表示新节点,referenceNode
表示目标节点,也就是新节点插入到目标节点之前。
3. 设置样式、属性
img.setAttribute('style', 'width: 100%; height: 100%;');
单独设置某些属性,如下代码:
dom.style.color = 'xxxx';
**setAttribute()**不仅仅可以设置style
之外,所有 HTML 属性都能用他设置,比如id
, src
, type
, disabled
, etc...
classList
classList
能获取到 DOM 上所有的类,所以我们也可以把样式写成css,然后再添加或删除class。
4. innerHTML
使用innerHTML = ''
清空select
节点所有的后代内容。
也可以利用innerHTML给某个元素添加内容。
function createDisease(txt) {
const dom = document.createElement('li');
// 我们可以直接用innerHTML设置其纯文本
dom.innerHTML = txt;
return dom;
}
DOM事件
DOM 绑定事件
// 监听Input输入事件
dom.addEventListener("input", function () {});
// 监听鼠标放置,移动事件
dom.addEventListener("mouseover", function () {});
// etc...
DOM 可以通过 addEventListener(eventName, callback)
绑定eventName
事件。
事件
焦点事件
focus : 表单组件(Input, Textarea, etc..)获取焦点事件 blur: 表单组件(Input, Textarea, etc..)失去焦点事件
鼠标事件
click : 点击事件 dblclick : 双击事件 mousedown : 在元素上按下任意鼠标按钮。 mouseenter : 指针移到有事件监听的元素内。 mouseleave : 指针移出元素范围外(不冒泡)。 mousemove : 指针在元素内移动时持续触发。 mouseover : 指针移到有事件监听的元素或者它的子元素内。 mouseout : 指针移出元素,或者移到它的子元素上。 mouseup: 在元素上释放任意鼠标按键。
键盘事件
keydown : 键盘按下事件 keyup: 键盘释放事件
视图事件
scroll : 文档滚动事件 resize: 窗口放缩事件
资源
load: 资源加载成功的事件
点击事件
// 默认是未点击喜欢
let hasLike = false;
const likeBtn = document.querySelector(".like-btn");
likeBtn.addEventListener("click", function () {
// 点击事件
hasLike = !hasLike;
console.log(hasLike);
});
冒泡
1.点击事件触发监听事件
2.冒泡找到其父亲节点,触发父亲节点的监听事件
3.依次冒泡直到html根元素为止。
阻止冒泡-e.stopPropagation();
// ......省略
likeBtn.addEventListener('click', function(e) {
// 点击事件
e.stopPropagation()
捕获
捕获和冒泡是完全相反的,冒泡是从当前元素沿着祖先节点往上冒泡,而捕获是从根 HTML 节点开始依次移动到当前元素。
我们上面使用的addEventListener
是在冒泡阶段监听事件,如果想在捕获阶段监听事件,我们需要传递第三个参数为true
, 代码如下
dom.addEventListener('click', function() {}, true);
委托
在大量子元素中单击任何一个都可以运行一段代码 ,可以将事件监听器设置在其父节点上,并让子节点上发生的事件冒泡到父节点上,而不是每个子节点单独设置事件监听器。
将
const box = document.querySelector('.box');
const imgArr = box.children;
for (let i = 0; i < imgArr.length; i++) {
imgArr[i].addEventListener('click', function() {
document.body.style.backgroundImage = `url(${imgArr[i].src})`;
});
}
修改为
const box = document.querySelector('.box');
box.addEventListener('click', function(e) {
// 注意box区域比img大,如果点击在空白间隔区域,那么返回的节点将不会是IMG,需要特殊处理一下
if (e.target.nodeName === 'IMG') {
document.body.style.backgroundImage = `url(${e.target.src})`;
}
});
移动事件
鼠标移动事件
mouseenter: 指针移到有事件监听的元素内。
mouseleave: 指针移出元素范围外(不冒泡)。
mousemove: 指针在元素内移动时持续触发。
mouseover: 指针移到有事件监听的元素或者它的子元素内。
mouseout: 指针移出元素,或者移到它的子元素上。
1. mousemove
这个是鼠标移动事件,比较简单
2. mouseenter/mouseleave
这个是鼠标进入和离开事件,但是仅仅只作用于当前 DOM 节点,不会作用于其后代节点
3. mouseover/mouseout
这个也是鼠标进入和离开事件,但和
enter/leave
不同的是:此事件除了作用于当前 DOM 节点,也会同时作用于其后代节点
表单元素事件
焦点事件
获取焦点和失去焦点两个事件 --- focus 和 blur。
内容值变化
监听元素内容变化 --- input 和 change。
const nick = document.querySelector('input.nick');
nick.addEventListener('input', function() {
console.log('-----input');
console.log(nick.value);
});
nick.addEventListener('change', function() {
console.log('-----change');
console.log(nick.value);
});
事件 | 介绍 | 案例 |
---|---|---|
change |
当用户提交对元素值的更改时触发; change 事件不一定会对元素值的每次更改触发 | 1. checkbox 值修改以后 2. select 选择后 3. input 内容修改并失去焦点 |
input |
只要 value 值修改就会触发 |
滚动事件
1. 无尽滚动
网页每次滚动到底部,会加载新内容,再次滚动到底部,又会加载新内容。
2. 动态效果
滚动一般用于展示一些动态效果,比如知乎头部
滚动事件,事件名称为 --- scroll。
键盘事件
keyboardEvent
KeyboardEvent
对象描述了用户与键盘的交互。每个事件都描述了用户与一个按键(或一个按键和修饰键的组合)的单个交互。