avaScript高级程序设计第四版学习--第十六章


title: JavaScript高级程序设计第四版学习–第十六章
date: 2021-5-26 20:43:17
author: Xilong88
tags: JavaScript

本章内容:

操作样式的DOM API
DOM遍历与范围
可能出现的面试题:
1.JavaScript操作CSS程序题
2.偏移尺寸,客户端尺寸,滚动尺寸是什么?区别?
3.了解过NodeIterator和TreeWalker,谈谈属性和方法
4.了解过范围操作DOM吗,有哪些方法?

总结:这章讲了一些操作DOM的属性和方法。还有遍历的方法。

知识点:

·1.存取元素样式

任何支持style 属性的HTML元素在JavaScript中都会有一个对应的style 属性

CSS属性名使用连字符表示法(用连字符分隔两个单词,如background-
image ),在JavaScript中这些属性必须转换为驼峰大小写形式(如backgroundImage )

在这里插入图片描述
任何时候,只要获得了有效DOM元素的引用,就可以通过JavaScript来设置样式。

let myDiv = document.getElementById("myDiv");
// 设置背景颜色
myDiv.style.backgroundColor = "red";
// 修改大小
myDiv.style.width = "100px";
myDiv.style.height = "200px";
// 设置边框
myDiv.style.border = "1px solid black";

某些属性记得带上单位px

DOM样式属性和方法

元素style 属性

cssText ,包含style 属性中的CSS代码。
length ,应用给元素的CSS属性数量。
parentRule ,表示CSS信息的CSSRule 对象(下一节会讨论
CSSRule 类型)。
getPropertyCSSValue(propertyName ) ,返回包含CSS属
性 propertyName 值的CSSValue 对象(已废弃)。
getPropertyPriority(propertyName ) ,如果CSS属性
propertyName 使用了!important 则返回"important" ,否
则返回空字符串。
getPropertyValue(propertyName ) ,返回属性
propertyName 的字符串值。

item(index ) ,返回索引为 index 的CSS属性名。
removeProperty(propertyName ) ,从样式中删除CSS属性
propertyName 。
setProperty(propertyName, value, priority ) ,设置
CSS属性 propertyName 的值为 value , priority
是"important" 或空字符串。

设置cssText 是一次性修改元素多个样式最快捷的方式,因为所有变化会同时生效。

计算样式

getComputedStyle() 方法返
回一个CSSStyleDeclaration 对象(与style 属性的类型一样),包含元素的计算样式

let myDiv = document.getElementById("myDiv");
let computedStyle = document.defaultView.getComputedStyle(myDiv, null);
console.log(computedStyle.backgroundColor);  // "red"
console.log(computedStyle.width);            // "100px"
console.log(computedStyle.height);           // "200px"
console.log(computedStyle.border);           // "1px solid black"(在某些浏览器中)

在所有浏览器中计算样式都是只读的,
不能修改getComputedStyle() 方法返回的对象。而且,计算样式还包含浏览器内部样式表中的信息。因此有默认值的CSS属性会出现在计算样式里。

2.操作样式表

CSSStyleSheet 类型继承StyleSheet ,后者可用作非CSS样式表的基类。以下是CSSStyleSheet 从StyleSheet 继承的属性。

disabled ,布尔值,表示样式表是否被禁用了(这个属性是可读
写的,因此将它设置为true 会禁用样式表)。
href ,如果是使用<link> 包含的样式表,则返回样式表的URL,
否则返回null 。
media ,样式表支持的媒体类型集合,这个集合有一个length 属
性和一个item() 方法,跟所有DOM集合一样。同样跟所有DOM
集合一样,也可以使用中括号访问集合中特定的项。如果样式表可
用于所有媒体,则返回空列表。
ownerNode ,指向拥有当前样式表的节点,在HTML中要么
是<link> 元素要么是<style> 元素(在XML中可以是处理指
令)。如果当前样式表是通过@import 被包含在另一个样式表中,
则这个属性值为null 。
parentStyleSheet ,如果当前样式表是通过@import 被包含在另
一个样式表中,则这个属性指向导入它的样式表。
title ,ownerNode 的title 属性。
type ,字符串,表示样式表的类型。对CSS样式表来说,就
是"text/css"

上述属性里除了disabled ,其他属性都是只读的。除了上面继承的属性,CSSStyleSheet 类型还支持以下属性和方法。

cssRules ,当前样式表包含的样式规则的集合。
ownerRule ,如果样式表是使用@import 导入的,则指向导入规
则;否则为nulldeleteRule(index ) ,在指定位置删除cssRules 中的规则。
insertRule(rule , index ) ,在指定位置向cssRules 中插入规则。

document.styleSheets 表示文档中可用的样式表集合。

CSSStyleRule 对象上可用的属性。

cssText ,返回整条规则的文本。这里的文本可能与样式表中
实际的文本不一样,因为浏览器内部处理样式表的方式也不一
样。Safari始终会把所有字母都转换为小写。
parentRule ,如果这条规则被其他规则(如@media )包
含,则指向包含规则,否则就是null 。
parentStyleSheet ,包含当前规则的样式表。
selectorText ,返回规则的选择符文本。这里的文本可能与
样式表中实际的文本不一样,因为浏览器内部处理样式表的方
式也不一样。这个属性在Firefox、Safari、Chrome和IE中是只
读的,在Opera中是可以修改的。
style ,返回CSSStyleDeclaration 对象,可以设置和获取
当前规则中的样式。
type ,数值常量,表示规则类型。对于样式规则,它始终为1
div.box {
  background-color: blue;
  width: 100px;
  height: 200px;
}
let sheet = document.styleSheets[0];
let rules = sheet.cssRules || sheet.rules;  // 取得规则集合
let rule = rules[0];                        // 取得第一条规则
console.log(rule.selectorText);             // "div.box"
console.log(rule.style.cssText);            // 完整的CSS代码
console.log(rule.style.backgroundColor);    // "blue"
console.log(rule.style.width);              // "100px"
console.log(rule.style.height);             // "200px"

创建规则

sheet.insertRule("body { background-color: silver }", 0);  // 使用DOM方法

删除规则

sheet.deleteRule(0);  // 使用DOM方法

3.元素尺寸

偏移尺寸

offsetHeight ,元素在垂直方向上占用的像素尺寸,包括它
的高度、水平滚动条高度(如果可见)和上、下边框的高度。
offsetLeft ,元素左边框外侧距离包含元素左边框内侧的像
素数。
offsetTop ,元素上边框外侧距离包含元素上边框内侧的像素
数。
offsetWidth ,元素在水平方向上占用的像素尺寸,包括它
的宽度、垂直滚动条宽度(如果可见)和左、右边框的宽度。

offsetLeft 和offsetTop 是相对于包含元素的,包含元素保存在offsetParent 属性中
在这里插入图片描述

客户端尺寸

元素的客户端尺寸 (client dimensions)包含元素内容及其内边距

所占用的空间。客户端尺寸只有两个相关属性:clientWidth 和clientHeight 。

在这里插入图片描述
滚动尺寸

最后一组尺寸是滚动尺寸 (scrolldimensions),提供了元素内容滚动距离的信息。

scrollHeight ,没有滚动条出现时,元素内容的总高度。
scrollLeft ,内容区左侧隐藏的像素数,设置这个属性可以
改变元素的滚动位置。
scrollTop ,内容区顶部隐藏的像素数,设置这个属性可以改
变元素的滚动位置。
scrollWidth ,没有滚动条出现时,元素内容的总宽度。

在这里插入图片描述
确定元素尺寸

浏览器在每个元素上都暴露了getBoundingClientRect() 方法,
返回一个DOMRect 对象,包含6个属性:left 、top 、right、bottom 、height 和width 。这些属性给出了元素在页面中相对于视口的位置。

在这里插入图片描述

4.遍历

DOM2 Traversal and Range模块定义了两个类型用于辅助顺序遍历DOM结构。这两个类型——NodeIterator 和TreeWalker ——从某个起点
开始执行对DOM结构的深度优先遍历。

NodeIterator

document.createNodeIterator() 方法创建其实例

接收以
下4个参数。

root ,作为遍历根节点的节点。
whatToShow ,数值代码,表示应该访问哪些节点。
filter ,NodeFilter 对象或函数,表示是否接收或跳过特定节
点。
entityReferenceExpansion ,布尔值,表示是否扩展实体引
用。这个参数在HTML文档中没有效果,因为实体引用永远不扩
展。

whatToShow 参数是一个位掩码,通过应用一个或多个过滤器来指定访
问哪些节点。这个参数对应的常量是在NodeFilter 类型中定义的。

NodeFilter.SHOW_ALL ,所有节点。
NodeFilter.SHOW_ELEMENT ,元素节点。
NodeFilter.SHOW_ATTRIBUTE ,属性节点。由于DOM的结构,
因此实际上用不上。
NodeFilter.SHOW_TEXT ,文本节点。
NodeFilter.SHOW_CDATA_SECTION ,CData区块节点。不是在
HTML页面中使用的。
NodeFilter.SHOW_ENTITY_REFERENCE ,实体引用节点。不是在
HTML页面中使用的。
NodeFilter.SHOW_ENTITY ,实体节点。不是在HTML页面中使用
的。
NodeFilter.SHOW_PROCESSING_INSTRUCTION ,处理指令节点。
不是在HTML页面中使用的。
NodeFilter.SHOW_COMMENT ,注释节点。
NodeFilter.SHOW_DOCUMENT ,文档节点。
NodeFilter.SHOW_DOCUMENT_TYPE ,文档类型节点。
NodeFilter.SHOW_DOCUMENT_FRAGMENT ,文档片段节点。不是
在HTML页面中使用的。
NodeFilter.SHOW_NOTATION ,记号节点。不是在HTML页面中
使用的。


以像下面这样使用按位或操作组合多个选项:

let whatToShow = NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT;
let filter = {
  acceptNode(node) {
    return node.tagName.toLowerCase() == "p" ?
         NodeFilter.FILTER_ACCEPT :
         NodeFilter.FILTER_SKIP;
  }
};
let iterator = document.createNodeIterator(root, NodeFilter.SHOW_ELEMENT,
                                           filter, false);

filter 参数还可以是一个函数,与acceptNode() 的形式一样,如下:

let filter = function(node) {
    return node.tagName.toLowerCase() == "p" ?
         NodeFilter.FILTER_ACCEPT :
         NodeFilter.FILTER_SKIP;
};
let iterator = document.createNodeIterator(root, NodeFilter.SHOW_ELEMENT,
                                           filter, false);

要创建一个简单的遍历所有节点的NodeIterator ,可以使用以下代码:

let iterator = document.createNodeIterator(document, NodeFilter.SHOW_ALL,
                                           null, false);

NodeIterator 的两个主要方法是nextNode() 和previousNode()

nextNode() 方法在DOM子树中以深度优先方式进前一步,而previousNode() 则是在遍历中后退一步。

<div id="div1">
  <p><b>Hello</b> world!</p>
  <ul>
    <li>List item 1</li>
    <li>List item 2</li>
    <li>List item 3</li>
  </ul>
</div>
let div = document.getElementById("div1");
let iterator = document.createNodeIterator(div, NodeFilter.SHOW_ELEMENT,
                                           null, false);
let node = iterator.nextNode();
while (node !== null) {
  console.log(node.tagName);     // 输出标签名
  node = iterator.nextNode();
}
DIV

P
B
UL
LI
LI
LI

如果只想遍历

  • 元素,可以传入一个过滤器,比如:
  • let div = document.getElementById("div1");
    let filter = function(node) {
      return node.tagName.toLowerCase() == "li" ?
        NodeFilter.FILTER_ACCEPT :
        NodeFilter.FILTER_SKIP;
    };
    let iterator = document.createNodeIterator(div, NodeFilter.SHOW_ELEMENT,
           filter, false);
    let node = iterator.nextNode();
    while (node !== null) {
      console.log(node.tagName);     // 输出标签名
      node = iterator.nextNode();
    }
    

    TreeWalker

    parentNode() ,遍历到当前节点的父节点。
    firstChild() ,遍历到当前节点的第一个子节点。
    lastChild() ,遍历到当前节点的最后一个子节点。
    nextSibling() ,遍历到当前节点的下一个同胞节点。
    
    previousSibling() ,遍历到当前节点的上一个同胞节点。
    
    节点过滤器(filter)除了可以返回
    NodeFilter.FILTER_ACCEPT 和NodeFilter.FILTER_SKIP ,还可以
    返回NodeFilter.FILTER_REJECT 。在使用NodeIterator
    时,NodeFilter.FILTER_SKIP 和NodeFilter.FILTER_REJECT 是一
    样的。但在使用TreeWalker 时,NodeFilter.FILTER_SKIP 表示跳过
    节点,访问子树中的下一个节点,而NodeFilter.FILTER_REJECT 则
    表示跳过该节点以及该节点的整个子树。
    

    5.范围

    DOM2在Document 类型上定义了一个createRange() 方法,暴露在document 对象上使用这个方法可以创建一个DOM范围对象,如下所示:

    let range = document.createRange();
    

    属性和方法:

    startContainer ,范围起点所在的节点(选区中第一个子节点的
    父节点)。
    startOffset ,范围起点在startContainer 中的偏移量。如果
    startContainer 是文本节点、注释节点或CData区块节点,
    则startOffset 指范围起点之前跳过的字符数;否则,表示范围
    中第一个节点的索引。
    endContainer ,范围终点所在的节点(选区中最后一个子节点的
    父节点)。
    endOffset ,范围起点在startContainer 中的偏移量
    (与startOffset 中偏移量的含义相同)。
    commonAncestorContainer ,文档中以startContainer 和
    endContainer 为后代的最深的节点。
    
    setStartBefore(refNode ) ,把范围的起点设置到 refNode
    之前,从而让 refNode 成为选区的第一个子节
    点。startContainer 属性被设置为refNode.parentNode ,
    而startOffset 属性被设置为refNode 在其父节点childNodes 集
    合中的索引。
    setStartAfter(refNode ) ,把范围的起点设置到 refNode 之
    后,从而将 refNode 排除在选区之外,让其下一个同胞节点成为
    选区的第一个子节点。startContainer 属性被设置
    为refNode.parentNode ,startOffset 属性被设置为refNode 在
    其父节点childNodes 集合中的索引加1setEndBefore(refNode ) ,把范围的终点设置到 refNode 之
    前,从而将 refNode 排除在选区之外、让其上一个同胞节点成为
    选区的最后一个子节点。endContainer 属性被设置
    为refNode.parentNode ,endOffset 属性被设置为refNode 在其
    父节点childNodes 集合中的索引。
    setEndAfter(refNode ) ,把范围的终点设置到 refNode 之
    后,从而让 refNode 成为选区的最后一个子节
    点。endContainer 属性被设置为refNode.parentNode
    ,endOffset 属性被设置为 refNode 在其父节点childNodes 集
    合中的索引加1 
    

    也就是说可以创建一个范围来控制DOM

    操作范围
    deleteContents()
    extractContents()
    insertNode()
    surroundContents()
    collapse()
    折叠:
    true 表示折叠到起点,false 表示折叠
    到终点。要确定范围是否已经被折叠,可以检测范围的collapsed 属性:

    range.collapse(true);          // 折叠到起点
    console.log(range.collapsed);  // 输出true
    compareBoundaryPoints()
    

    意思是折叠起来的部分不会被选择

    Range.START_TO_START0),比较两个范围的起点;
    Range.START_TO_END1),比较第一个范围的起点和第二个范
    围的终点;
    Range.END_TO_END2),比较两个范围的终点;
    Range.END_TO_START3),比较第一个范围的终点和第二个范围的起点。
    

    compareBoundaryPoints() 方法在第一个范围的边界点位于第二个范围的边界点之前时返回-1 ,在两个范围的边界点相等时返回0 ,在第一个范围的边界点位于第二个范围的边界点之后时返回1 。来看下面的例子:

    let range1 = document.createRange();
    let range2 = document.createRange();
    let p1 = document.getElementById("p1");
    
    range1.selectNodeContents(p1);
    range2.selectNodeContents(p1);
    range2.setEndBefore(p1.lastChild);
    console.log(range1.compareBoundaryPoints(Range.START_TO_START, range2));  // 0
    console.log(range1.compareBoundaryPoints(Range.END_TO_END, range2));      // 1
    

    cloneRange()

    range.detach();  // 从文档中剥离范围
    
    range = null;    // 解除引用
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值