BOM与DOM事件
# 浏览器内核
safari Webkit
chrome Blink (current) / Webkit (pre) -webkit-
chromium Blink
firefox Gecko -moz-
ie Trident -ms-
edge EdgeHTML
Opera12.17及更早版本曾经采用的内核 Presto -o-
2
3
4
5
6
7
# 文档基本结构
document.head; // 文档的头标签
typeof document.head; // object
document.title; // 文档标题
typeof document.title; // string
document.body; // 文档的body标签
typeof document.body; // object
document.documentElement; // 文档的根节点 注意:没有document.html这个东西
typeof document.documentElement; // object
document.html; // 这个是错的!!!
document.defaultView === window; // true
document.activeElement; // 属性返回当前文档中获得焦点的那个元素
document.defaultView;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 文档兼容模式
document type
声明文档类型 DTD:<!DOCTYPE html>
BackCompat
未声明 DTD(怪异模式)firefoxCSS1Compat
已经声明 DTD(标准模式)chrome ,iedocument.compatMode
获取文档类型
# document
# 节点集合属性
document.links
属性返回当前文档所有设定了 href 属性的 a 及 area 元素document.images
属性返回页面所有图片元素(即 img 标签)document.scripts
属性返回当前文档的所有脚本(即 script 标签)document.styleSheets
属性返回一个类似数组的对象,代表当前网页的所有样式表
# 文档信息属性
document.documentURI
属性和document.URL
属性都返回一个字符串,表示当前文档的网址documentURI
属性可用于所有文档(包括 XML 文档),URL 属性只能用于 HTML 文档document.domain
属性返回当前文档的域名document.lastModified
属性返回当前文档最后修改的时间戳,格式为字符串document.title
属性返回当前文档的标题,该属性是可写的document.referrer
document.characterSet
属性返回渲染当前文档的字符集 //UTF-8document.readyState
属性返回当前文档的状态三种可能的值:
loading
:加载 HTML 代码阶段(尚未完成解析)interactive
:加载外部资源阶段时complete
:加载完成时
document.designMode
属性控制当前文档是否可编辑document.implementation
属性返回一个对象,用来甄别当前环境部署了哪些 DOM 相关接口implementation
属性的hasFeature
方法,可以判断当前环境是否部署了特定版本的特定接口
document.implementation.hasFeature("HTML", "2.0"); // true
document.implementation.hasFeature("MutationEvents", "2.0"); // true
2
3
document.cookie
属性用来操作浏览器 Cookie
# 类型
Document
:整个文档树的顶层节点DocumentType
:doctype 标签(比如<!DOCTYPE html>
)Element
:网页的各种 HTML 标签(比如<body>、<a>
等)Attribute
:网页元素的属性(比如class="right"
)Text
:标签之间或标签包含的文本Comment
:注释DocumentFragment
:文档的片段
# 获取 DOM 元素
- 获取节点
document.querySelector("#demo"); //只返回匹配的第一个元素dom html5
document.querySelectorAll(".test"); // html5
// 通过id号来获取元素,返回一个元素对象
document.getElementById(idName)
// 通过name属性获取id号,返回元素对象数组
document.getElementsByName(name)
// 通过class来获取元素,返回元素对象数组
document.getElementsByClassName(className)
// 通过标签名获取元素,返回元素对象数组
document.getElementsByTagName(tagName)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
- 获取/设置元素的属性值
// 括号传入属性名,返回对应属性的属性值
element.getAttribute(attributeName)
// 传入属性名及设置的值
element.setAttribute(attributeName,attributeValue)
2
3
4
5
- 创建节点Node
// 创建一个html元素,这里以创建h3元素为例
document.createElement("h3")
// 创建一个文本节点;
document.createTextNode(String);
// 创建一个属性节点,这里以创建class属性为例
document.createAttribute("class");
2
3
4
5
6
7
8
- 增添节点
// 往element内部最后面添加一个节点,参数是节点类型
element.appendChild(Node);
// 在element内部的中在existingNode前面插入newNode
elelment.insertBefore(newNode,existingNode);
// insertAdjacentHTML: (beforebegin | afterbegin | beforeend | afterend)
element.insertAdjacentHTML(position, text)
2
3
4
5
6
7
8
- 删除节点
//删除当前节点下指定的子节点,删除成功返回该被删除的节点,否则返回null
element.removeChild(Node)
2
3
# DOM常用属性
- 获取当前元素的父节点
// 返回当前元素的父节点对象
element.parentNode
2
- 获取当前元素的子节点
// 返回当前元素所有子元素节点对象,只返回HTML节点
element.chlidren
// 返回当前元素多有子节点,包括文本,HTML,属性节点。(回车也会当做一个节点)
element.chilidNodes
// 返回当前元素的第一个子节点对象
element.firstChild
// 返回当前元素的最后一个子节点对象
element.lastChild
2
3
4
5
6
7
8
9
10
11
- 获取当前元素的同级元素
// 返回当前元素的下一个同级元素 没有就返回null
element.nextSibling
// 返回当前元素上一个同级元素 没有就返回 null
element.previousSibling
2
3
4
5
- 获取当前元素的文本
// 返回元素的所有文本,包括html代码
element.innerHTML
// 返回当前元素的自身及子代所有文本值,只是文本内容,不包括html代码
element.innerText
2
3
4
5
- 获取当前节点的节点类型
类型 | nodeName | nodeType |
---|---|---|
ELEMENT_NODE | 大写的 HTML 元素名 | 1 |
ATTRIBUTE_NODE | Attr.name | 2 |
TEXT_NODE | #text | 3 |
COMMENT_NODE | #comment | 8 |
DOCUMENT_NODE | #document | 9 |
DOCUMENT_TYPE_NODE | DocumentType.name | 10 |
DOCUMENT_FRAGMENT_NODE | #document-fragment | 11 |
document.nodeName; // "#document"
document.nodeType; // 9
document.querySelector("a").nodeType === 1; // true
document.querySelector("a").nodeType === Node.ELEMENT_NODE; // true
2
3
4
- 设置样式
// 设置元素的样式时使用style
element.style.color="#eea";
2
# 节点对象属性
# Node.nodeValue
返回一个字符串,表示当前节点本身的文本值,该属性可读写
# Node.textContent
返回当前节点和它的所有后代节点的文本内容
自动忽略当前节点内部的HTML标签,返回所有文本内容
# Node.sibling 与 Node.previousSibling
Node.nextSibling属性返回紧跟在当前节点后面的第一个同级节点
Node.previousSibling属性返回当前节点前面的、距离最近的一个同级节点
nextSibling
:IE678 (下一个兄弟节点)- 在谷歌火狐中也有这个方法,只不过是得到换行.
nextElementSibling
:火狐谷歌 IE9-11 (下一个兄弟节点)- 兼容写法:
b.nextElementSibling || b.nextSibling
<div class="box"></div>
<div class="box" id="box"></div>
<div class="box"></div>
//1.获取id名为box的盒子.
var b = document.getElementById("box");
//2.通过兄弟节点的方式获得下盒子
var n = b.nextElementSibling || b.nextSibling;
//3.更改背景色
n.style.backgroundColor = "purple";
2
3
4
5
6
7
8
9
previousSibling
:IE678 (上一个兄弟节点)- 在谷歌火狐中也有这个方法,只不过是得到换行.
previousElementSibling
:火狐谷歌 IE9-11 (上一个兄弟节点)- 兼容写法:
b.previousElementSibling || b.previousSibling
//1.获取id名为box的盒子.
var b = document.getElementById("box");
//2.兄弟节点的方式获得上盒子
var m = b.previousElementSibling || b.previousSibling;
//3.更改背景色
m.style.backgroundColor = "purple";
// 获取所有的兄弟节点
function siblings(elm) {
var a = [];
var p = elm.parentNode.children;
for (var i = 0, pl = p.length; i < pl; i++) {
if (p[i] !== elm) {
a.push(p[i]);
}
return a;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Node.parentNode
返回当前节点的父节点
- 只可能是三种类型:
element、 document和documentfragment
//从父节点移除指定节点
if (node.parentNode) {
node.parentNode.removeChild(node);
}
2
3
4
# Node.parentElement
- 返回当前节点的父 Element 节点
- 如果当前节点没有父节点,或者父节点类型不是 Element 节点,则返回
null
//设置指定节点的父Element节点的CSS属性
if (node.parentElement) {
node.parentElement.style.color = "red";
}
2
3
4
# Node.childNodes
火狐谷歌 IE9-11 (所有子节点)
nodeType
每一个标签都一个这个属性(有个三个值)nodeType == 1
表示的是元素节点nodeType == 2
表示是属性节点nodeType == 3
是文本节点
<div id="box">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
<script>
//1.获取父盒子
var b = document.getElementById("box");
//2.通过父盒子获取所有子盒子
var bcArr = b.childNodes;
var arr = [];
//for循环遍历得到的所有自盒子数组
for (var i = 0; i < bcArr.length; i++) {
//如果自盒子的nodeType的值 == 1 ,说明他的是元素节点(标签)
if (bcArr[i].nodeType == 1) {
//把这个标签放入arr 这个数组.
arr.push(bcArr[i]);
}
}
//3.打印长度.()
console.log(bcArr);
console.log(bcArr.length);
console.log(arr);
console.log(arr.length);
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# Node.firstChild 与 Node.lastChild
firstChild属性返回当前节点的第一个子节点,如果当前节点没有子节点,则返回null
Node.lastChild属性返回当前节点的最后一个子节点,如果当前节点没有子节点,则返回null
firstChild
:IE678 (第一个子节点)- 在谷歌火狐中也有这个方法,只不过是得到第一个换行.
firstElementChild
:火狐谷歌 IE9-11 (第一个子节点)- 兼容写法:
b.firstElementChild || b.firstChild
<div id="box">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
<script>
//1.获取父盒子
var b = document.getElementById("box");
//2.通过父盒子获取第一个子盒子
var fc = b.firstElementChild || b.firstChild;
//3.更改背景色.
fc.style.backgroundColor = "purple";
</script>
2
3
4
5
6
7
8
9
10
11
12
13
lastChild
:IE678 (最后一个子节点)- 在谷歌火狐中也有这个方法,只不过是得到最后一个换行.
lastElementChild
:火狐谷歌 IE9-11 (最后一个子节点)- 兼容写法:
b.lastElementChild || b.lastChild
//1.获取父盒子
var b = document.getElementById("box");
//2.通过父盒子获取最后一个子盒子
var lc = b.lastElementChild || b.lastChild;
//3.更改背景色.
lc.style.backgroundColor = "purple";
2
3
4
5
6
# children
- 在 IE678 中注释会被当做节点.解决方法:
注释写到父节点外部
<div id="box">
<div class="box"></div>
<div class="box"></div>
<!--这个是第三个盒子-->
<div class="box"></div>
</div>
<script>
//1.获取父盒子
var b = document.getElementById("box");
//2.通过父盒子获取所有子盒子
var bcArr = b.children;
//3.打印长度
console.log(bcArr);
console.log(bcArr.length);
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# DOM 节点对象的方法
# createElement
newNode = document.createElement(“标签名”)
// 创建一个html元素,这里以创建h3元素为例
document.createElement("h3")
// 创建一个文本节点;
document.createTextNode(String);
// 创建一个属性节点,这里以创建class属性为例
document.createAttribute("class");
//demo
newel = document.createElement("h1");
newel.innerHTML = "<p>hello</p>"; //innerText不能转换HTML标签
document.body.appendChild(newel);
//demo2
newtext = document.createTextNode("hello world");
document.body.appendChild(newtext);
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 节点的添加
# appendChild
Node.appendChild()
:接受一个节点对象作为参数,将其作为最后一个子节点
,插入当前节点
// 往element内部最后面添加一个节点,参数是节点类型
element.appendChild(Node);
// 在element内部的中在existingNode前面插入newNode
elelment.insertBefore(newNode,existingNode);
2
3
4
5
6
# hasChildNodes
Node.hasChildNodes()
:返回一个布尔值,表示当前节点是否有子节点
function DOMComb(parent, callback) {
if (parent.hasChildNodes()) {
for (var node = parent.firstChild; node; node = node.nextSibling) {
DOMComb(node, callback);
}
}
callback.call(parent);
}
2
3
4
5
6
7
8
# insertBefore
insertBefore(a,b)
用于将某个节点插入当前节点的指定位置- 该方法接受 2 个参数,第一个是
要插入的节点
,第二个是参照节点
parentNode.insertBefore(newNode,targetNode);
// 往element内部最后面添加一个节点,参数是节点类型
element.appendChild(Node);
// 在element内部的中在existingNode前面插入newNode
elelment.insertBefore(newNode,existingNode);
2
3
4
5
6
# insertAdjacentHTML
Element.insertAdjacentHTML方法解析HTML字符串;然后将生成的节点插入DOM树的指定位置
element.insertAdjacentHTML(position, text);
第一个是指定位置;第二个是待解析的字符串beforebegin
:插入到指定元素前面
// <div id="parent"></div> let parent = document.getElementById('parent'); let node = document.createElement('span'); // 等价于 $(parent).after(node); parent.insertAdjacentElement('beforebegin', node);
1
2
3
4
5afterbegin
:插入到指定元素内部的头部
// <div id="parent"></div> let parent = document.getElementById('parent'); let node = document.createElement('span'); // 等价于 $(parent).prepend(node); parent.insertAdjacentElement('afterbegin', node);
1
2
3
4
5beforeend
:插入到指定元素内部的尾部
// <div id="parent"></div> let parent = document.getElementById('parent'); let node = document.createElement('span'); // 等价于 $(parent).append(node); parent.insertAdjacentElement('beforeend', node);
1
2
3
4
5afterend
:插入到指定元素后面
// <div id="parent"></div> let parent = document.getElementById('parent'); let node = document.createElement('span'); // 等价于 $(parent).after(node); parent.insertAdjacentElement('afterend', node);
1
2
3
4
5Element.remove方法用于将当前元素节点从DOM树删除
Element.focus方法用于将当前页面的焦点
# cloneNode
cloneNode(参数) ;booblean类型的参数.
newNode = oldNode.cloneNode(boolean) ;
用于复制节点, 接受一个布尔值参数true
表示深复制(复制节点及其所有子节点),false
表示浅复制(复制节点本身,不复制子节点
<div id="box">
<div id="box1">
<div>1</div>
<div>2</div>
</div>
</div>
<script>
var box = document.getElementById("box");
var box1 = document.getElementById("box1");
var newBox = box1.cloneNode(true);
// var newBox = box1.cloneNode(false);
box.appendChild(newBox);
</script>
2
3
4
5
6
7
8
9
10
11
12
13
# removeChild
parentNode.removeChild(childNode)
currentNode.parentNode.removeChild(currentNode)
不知道父级的情况下移除自身 Node
<div id="box">
<div id="box1"></div>
<div id="box2"></div>
</div>
<script>
var box = document.getElementById("box");
var box1 = document.getElementById("box1");
var box2 = document.getElementById("box2");
box.removeChild(box2);
box1.parentNode.removeChild(box1);
</script>
2
3
4
5
6
7
8
9
10
11
# replaceChild
- 用于将一个新的节点(替换当前节点的某一个子节点
replacedNode = parentNode.replaceChild(newChild, oldChild);
# Node.contains
- 一个节点作为参数(返回一个布尔值(表示参数节点是否为当前节点的后代节点
nodeA.contains(nodeB)
// 判断元素是否body元素且是否是body的子孙元素.
function isInPage(node) {
return (node === document.body) ? false : document.body.contains(node);
}
2
3
4
# isEqualNode
- 返回一个布尔值,用于检查两个节点是否相等
- 所谓相等的节点,指的是两个节点的类型相同、属性相同、子节点相同
nodeA.isEqualNode(nodeB)
# 节点的属性
Element.getAttribute
返回当前元素节点的指定属性.如果指定属性不存在;则返回null
Element.setAttribute
用于为当前元素节点新增属性.如果同名属性已存在;则相当于编辑已存在的属性Element.hasAttribute
返回一个布尔值;表示当前元素节点是否包含指定属性Element.removeAttribute
用于从当前元素节点移除属性
<img id="pic" width="100px" height="100px" />;
//1.获取节点.
var pic = document.getElementById("pic");
//2.修改属性.
pic.setAttribute("width", "500px");
var a = pic.getAttribute("height");
//3.删除属性
pic.removeAttribute("height");
2
3
4
5
6
7
8
# dataset 属性
data-
后面的属性名有限制;只能包含字母、数字、连词线(-)、点(.)、冒号(:)和下划线(_)
- 属性名不应该使用 A 到 Z 的大写字母;比如不能有
data-helloWorld
这样的属性名;而要写成data-hello-world
// html
<div id="mydiv" foo="bar"></div>
// js
var n = document.getElementById('mydiv');
n.getAttribute('foo') // bar
n.setAttribute('foo', 'baz')
n.removeAttribute('baz')
// html
<div id="mydiv2" data-foo="bar"></div>
// js
var n2 = document.getElementById('mydiv2');
n2.dataset.foo // bar
n2.dataset.foo = 'baz'
delete n2.dataset.foo;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# DocumentFragment
DocumentFragment 节点代表一个文档的片段,本身就是一个完整的 DOM 树形结构。 它没有父节点,parentNode 返回 null,但是可以插入任意数量的子节点。 它不属于当前文档,操作 DocumentFragment 节点,要比直接操作 DOM 树快得多
//var docFrag = document.createDocumentFragment();
// or
var docFrag = new DocumentFragment();
var li = document.createElement("li");
li.textContent = "Hello World";
docFrag.appendChild(li);
console.log(docFrag.textContent); //Hello World
document.querySelector("ul").appendChild(docFrag);
console.log(docFrag.textContent); // ''
2
3
4
5
6
7
8
9
10
# Element.Node兼容
- 获取下一个紧邻的兄弟元素
// 获取下一个紧邻的兄弟元素
function getNextElement(element) {
var ele = element;
if (ele.nextElementSibling) return ele.nextElementSibling;
do {
ele = ele.nextSibling;
} while (ele && ele.nodeType !== 1);
return ele;
}
2
3
4
5
6
7
8
9
- 获取上一个紧邻的兄弟元素
// 获取上一个紧邻的兄弟元素
function getPreviousElement(element) {
var ele = element;
if (ele.perviousElementSibling) return ele.perviousElementSibling;
do {
ele = ele.perviousSibling;
} while (ele && ele.nodeType !== 1);
return ele;
}
2
3
4
5
6
7
8
9
- 获取第一个子元素
// 获取第一个子元素
function getFirstElement(parent) {
if (parent.firstElementChild) return parent.firstElementChild;
var ele = parent.firstChild;
while (ele && ele.nodeType !== 1) ele = ele.nextSibling;
return ele;
}
2
3
4
5
6
7
- 获取最后一个子元素
// 获取最后一个子元素
function getLastElement(parent) {
if (parent.LastElementChild) return parent.LastElementChild;
var ele = parent.lastChild;
while (ele && ele.nodeType !== 1) ele = ele.perviousSibling;
return ele;
}
2
3
4
5
6
7
- 取所有兄弟元素
// 获取所有兄弟元素
function getAllSibling(ele) {
if (!ele) return null;
var elements = [];
var el = ele.previousSibling;
while (el) {
if (el.nodeType === 1)
elements.push(el);
el = el.previousSibling;
}
el = element.nextSibling;
while (el) {
if (el.nodeType === 1)
elements.push(el);
el = el.nextSibling;
}
return elements;
}
// 查找所有兄弟节点
function siblings(elm) {
var a = [];
var p = elm.parentNode.children;
for (var i = 0, pl = p.length; i < pl; i++) {
if (p[i] !== elm) {
a.push(p[i]);
}
return a;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# BFC
- Block Formatting Context 块级格式化上下文,形成独立渲染区域
- 前端精选文摘:BFC 神奇背后的原理 (opens new window)
# 如何触发 BFC
- 根元素 : 在块格式化上下文中
- float的值不为none
- position为absolute或fixed
- display的值为 inline-block, flex, inline-flex,table,table-cell,table-caption中的其中一个
- overflow的值不为visible
# Flex
https://www.ruanyifeng.com/blog/2015/07/flex-grammar.html (opens new window)
- flex-direction: row | row-reverse | column | column-reverse; 属性决定主轴的方向, 默认row
- flex-wrap: nowrap | wrap | wrap-reverse;
- flex-flow: flex-direction | flex-wrap;
- justify-content: flex-start | flex-end | center | space-between | space-around; 属性定义了项目在主轴上的对齐方式
- align-items: flex-start | flex-end | center | baseline | stretch; 属性定义项目在交叉轴上如何对齐
- flex :flex-grow flex-shrink flex-basis
flex: auto (1 1 auto) 和 none (0 0 auto)
flex-grow 属性定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大
flex-shrink 属性定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小
flex-basis 属性定义了在分配多余空间之前,项目占据的主轴空间(main size)
2
3
4
5
# position 定位
静态定位(标准流) :
position:static
绝对定位 :
position:absolute
- 绝对定位的盒子不占页面上的位置(脱离标准流)
- 绝对定位以后会影响元素的显示方式:display:inline-block
相对定位 :
position:relative
- 相对定位是占据标准流的位置
- 相对自身的位置进行定位
固定定位 :
position:fixed;
- 使用盒子显示浏览器的固定位置
- 固定定位会脱离标准流
- 固定定位会改变元素的显示方式
粘性定位元素 :
position:stickily
z-index:用来设置当前盒子所在的层次
z-index:12;
# 盒子模型分类
IE 盒子模型:
IE的content部分包含了 border 和 padding;
标准 W3C 盒子模型
width:border-left + padding-left + width + padding-right + border-right
height: border-top + padding-top + height + padding-bottom + border-bottom
# css3 盒模型属性
box-sizing: border-box
: 计算方式为width = border + padding + content
box-sizing: content-box
: 计算方式为width = content