《JavaScript高级程序设计》读书笔记
Selectors API
document.querySelector(selectors)
方法返回文档中与指定选择器或选择器组匹配的第一个 Element对象。 如果找不到匹配项,则返回null。
parentNode.querySelectofAll(selectors)
返回与指定的选择器组匹配的文档中的元素列表 (使用深度优先的先序遍历文档的节点)。返回的对象是NodeList。
element.matches(selectorSting)
如果元素匹配则该选择符返回true,否则返回false。
if(document.body.matches("body.page1")) {
// true
}
元素遍历
IE9 之前的版本不会把元素间的空格当成空白节点,而其他浏览器则会。这样就导致了 childNodes
和 firstChild 等属性上的差异。为了弥补这个差异,同时不影响 DOM 规范, W3C 通过新的 Element Traversal 规范定义了一组新属性。
- childElementCount 返回子元素数量(不包含文本节点和注释)
- firstElementChild 指向第一个 Element 类型的子元素
- lastElementChild 指向最后一个 Element 类型的子元素
- previousElementSibling 指向前一个Element类型的同胞元素
- nextElementSibling 指向后一个 Element 类型的同胞元素
HTML5
1. getElementByClassName()
参数接收一个包含一个或多个类名的字符串,返回类名中包含相应类的元素的NodeList。
2. classList 属性
操作类名,可以通过className 属性实现添加、删除和替换。
// 要删除"user"类
let targetClass = "user";
// 把类名拆成数组
let classNames = div.className.split(/\s+/);
// 找到要删除类名的索引
let idx = classNames.indexOf(targetClass);
// 如果有则删除
if (idx > -1) {
classNames.splice(i,1);
}
// 重新设置类名
div.className = classNames.join(" ");
classList 方法:
- add(value)
- contatins(value) 表示给定的value 是否存在
- remove(value)
- toggle(value) 如果类名列表中已经存在指定的value,则删除;如果不存在,则添加。
div.classList.remove("user");
div.class.add("current");
焦点管理
document.activeElement:始终包含当前拥有焦点的DOM元素。默认情况下,在页面刚加载完之后会设置为document.body。而页面完全加载之前,则为null。
document.hasFocus():返回布尔值,表示文档是否拥有焦点。
let button = document.getElementById("myButton");
button.focus();
console.log(document.activeElement === button); // true
console.log(document.hasFocus()); // true
HTMLDocument 扩展
1. readyState 属性
判断文档是否加载完毕,有两个可能的值:
- loading:表示文档正在加载
- complete:表示文档加载完成
2. compatMode属性
指示浏览器当前处于什么渲染模式。标准模式下是 CSS1Compat,混杂模式下是 BackCompat。
if(document.compatMode == "CSS1Compat") {
console.log("Standards mode");
} else {
console.log("Quirks mode");
}
字符集属性
document.characterSet:可以获取或修改
自定义数据属性
HTML5 允许给元素指定非标准的属性,但要使用前缀data- 以便告诉浏览器。可以通过dataset 属性访问。
let div = document.getElementById("myDiv");
// 取得自定义数据属性的值
let appId = div.dataset.appId;
let myName = div.dataset.myname;
// 设置自定义数据属性的值
div.dataset.appId = 23456;
div.dataset.myname = "Michael";
// 有"myname"吗?
if (div.dataset.myname){
console.log(`Hello, ${div.dataset.myname}`);
}
插入标记
1. innerHTML 属性
在读取 innerHTML 属性时,会返回元素所有后代的 HTML 字符串,包括元素、注释和文本节点。
而在写入 innerHTML 时,则会根据提供的字符串值以新的 DOM 子树替代元素中原来包含的所有节点。
2. outerHTML 属性
读取 outerHTML 属性时,会返回调用它的元素(及所有后代元素)的 HTML 字符串。在写入
outerHTML 属性时,调用它的元素会被传入的 HTML 字符串经解释之后生成的 DOM 子树取代。
4. insertAdjacentHTML()与 insertAdjacentText()
接收两个参数:要插入标记的位置和要插入的HTML或文本。
第一个参数必须是下列值中一个:
- "beforebegin" 插入当前元素前面,作为前一个同胞节点;
- "afterbegin" 插入当前元素内部,作为新的子节点或放在第一个子节点前面;
- "beforeend" 插入当前元素内部,作为新的子节点或放在最后一个子节点后面;
- "afterend" 插入当前元素后面,作为下一个同胞节点。
element.insertAdjacentHTML("beforebegin", "<p>Hello world!</p>");
element.insertAdjacentText("beforeend", "Hello world!");
scrollIntoView()
可以滚动浏览器窗口或容器元素以便包含元素进入视口。参数如下:
- alignToTop 是一个布尔值。
- true:窗口滚动后元素的顶部与视口顶部对齐。
- false:窗口滚动后元素的底部与视口底部对齐。
- scrollIntoViewOptions 是一个选项对象。
- behavior:定义过渡动画,可取的值为"smooth"和"auto",默认为"auto"。
- block:定义垂直方向的对齐,可取的值为"start"、 "center"、 "end"和"nearest",默认为 "start"。
- inline:定义水平方向的对齐,可取的值为"start"、 "center"、 "end"和"nearest",默认为 "nearest"。
- 不传参数等同于 alignToTop 为 true。
// 确保元素可见
document.forms[0].scrollIntoView();
// 同上
document.forms[0].scrollIntoView(true);
document.forms[0].scrollIntoView({block: 'start'});
// 尝试将元素平滑地滚入视口
document.forms[0].scrollIntoView({behavior: 'smooth', block: 'start'});
专有扩展
children 属性
children 属性是一个 HTMLCollection,只包含元素的 Element 类型的子节点。如果元素的子节点类型全部是元素类型,那 children 和 childNodes 中包含的节点应该是一样的。
let childCount = element.children.length;
let firstChild = element.children[0];
contains() 方法
确定一个元素是不是另一个元素的后代。如果目标节点是被搜索节点的后代, contains()返回 true,否则返回 false。
console.log(document.documentElement.contains(document.body)); // true
DOM Level 3 的 compareDocumentPosition()方法也可以确定节点间的关系。这个方法会返回表示两个节点关系的位掩码。下表给出了这些位掩码的说明。
掩码 | 节点关系 |
---|---|
0x1 | 断开(传入的节点不在文档中) |
0x2 | 领先(传入的节点在 DOM 树中位于参考节点之前) |
0x4 | 随后(传入的节点在 DOM 树中位于参考节点之后) |
0x8 | 包含(传入的节点是参考节点的祖先) |
0x10 | 被包含(传入的节点是参考节点的后代) |
let result = document.documentElement.compareDocumentPosition(document.body);
console.log(!!(result & 0x10));
插入标记
非标准的,请尽量不要在生产环境中使用它!
1. innerText 属性
对应元素中包含的所有文本内容,无论文本在子树中哪个层级。在用于读取值时,innerText 会按照深度优先的顺序将子树中所有文本节点的值拼接起来。在用于写入值时,innerText 会移除元素的所有后代并插入一个包含该值的文本节点。
2. outerText 属性
返回与HTMLElement.innerText一致的值。
滚动
scrollIntoViewIfNeeded(alingCenter)会在元素不可见的情况下,将其滚动到窗口或包含窗口中,使其可见;如果已经在视口中可见,则这个方法什么也不做。如果将可选的参数 alingCenter 设置为 true,则浏览器会尝试将其放在视口中央。
// 如果不可见,则将元素可见
document.images[0].scrollIntoViewIfNeeded();
考虑到 scrollIntoView()是唯一一个所有浏览器都支持的方法,所以只用它就可以了。