我们可以编写相应的 DOM 代码,如将返回的元素结果保存到变量中:
const nanodegreeCard = document.querySelector('.card');
更新现有页面内容
元素的内部 HTML
每个元素都从元素接口继承属性和方法
。这意味着,每个元素都有一个 .innerHTML
属性。这个属性顾名思义,表示元素内容的标记
。我们可以使用这个属性来:
获取
元素(及其所有子代!
)的 HTML 内容设置
元素的 HTML 内容
该属性返回的是一个字符串,也叫 DOMString
。
注意,.innerHTML
属性可以设置或返回所选元素内部
(即标签之间
)的 HTML 内容。还有一个很少使用的 .outerHTML
属性。.outerHTML
表示 HTML 元素本身,以及它的子元素
。
<h1 id="pick-me">大家<span>好</span>!</h1>
const innerResults = document.querySelector('#pick-me').innerHTML;
console.log(innerResults); // 会打印字符串:"大家<span>好</span>!"
const outerResults = document.querySelector('#pick-me').outerHTML;
console.log(outerResults); // 会打印字符串:"<h1 id="pick-me">大家<span>好</span>!</h1>"
元素的文本内容
.textContent
属性可以:
- 设置元素及其所有子代的文本内容
- 返回元素及其所有子代的文本内容
请查看 MDN 上的 .textContent 文档页面:textContent 文档
设置元素的文本内容很简单,就像设置任何其他属性一样:
nanodegreeCard.textContent = "I will be the updated text for the nanodegreeCard element!";
注意,将任何看起来像是 HTML 的文本
传递给 .textContent
属性,结果仍将显示为文本
。当元素被渲染时,它不会被显示为 HTML
。
const myElement = document.querySelector('#test');
myElement.textContent = 'The <strong>Greatest</strong> Ice Cream Flavors';
// 运行这段代码后,.textContent 值
// The <strong>Greatest</strong> Ice Cream Flavors
如果你想更新一个元素,包括它的 HTML,则需要使用 .innerHTML
属性:
myElement.textContent = 'The <strong>Greatest</strong> Ice Cream Flavors'; // 与预期不符
myElement.innerHTML = 'The <strong>Greatest</strong> Ice Cream Flavors'; // 与预期相符
在 DOM 中选中该元素,使用 $0
将此元素存储到变量中。然别使用元素的 .textContent
和 .innerHTML
方法观察变化。
.innerText
属性与 .textContent
属性一样,.innerText
属性可以用于获取/设置元素的文本内容,但这两个属性之间有一些重要的区别。
.innerText
会获取元素的可见文本。这是一个重要的区别!如果使用了 CSS 来隐藏该元素内的任何文本,.innerText
将不会返回该文本,而 .textContent
则会返回该文本。而且,.innerText
不仅遵循 CSS 的隐藏/显示性质,.innerText
还会遵循像大小写这样的更改。
.textContent
属性成为标准已有一段时间。相反,.innerText
属性则是 HTML 规范中相对较新的一个。虽然它出现已经有一段时间了,但并没有获得所有浏览器的完全支持,因为它不是 HTML 规范的一部分。
MDN 上的 innerHTML
MDN 上的 textContent
添加新的页面内容
.createElement()
方法是 document
对象上的一个方法:
// 创建并返回一个 <span> 元素
document.createElement('span');
// 创建并返回一个 <h3> 元素
document.createElement('h3');
这是 MDN 上的 .createElement() 文档页面:createElement 文档
使用 document.createElement()
来创建元素,其实并不会在页面上的任何位置添加新创建的元素,并不会将其添加到 DOM,因此它不会出现在页面上(如果你还记得,DOM 就是页面的解析表示
)。如何将创建的元素内容添加到对应的位置上?
我们可以使用 .appendChild()
方法向页面添加元素!要使用 .appendChild()
方法,需要在另一个元素上调用它,而不是 document
对象!
// 创建一个全新的 <span> 元素
const newSpan = document.createElement('span');
// 选择页面中的第一个(主)标题
const mainHeading = document.querySelector('h1');
// 添加 <span> 元素作为主标题的最后一个子元素
mainHeading.appendChild(newSpan);
在一个元素上调用 .appendChild()
方法,并将该元素传递给它进行附加。所附加的元素会被添加为最后一个子元素。
这是 MDN 上的 .appendChild() 文档页面:appendChild 文档
示例,创建一个新的 <div>
并且插入到 ID 为“div1”的元素前。
<!DOCTYPE html>
<html>
<head>
<title>||Working with elements||</title>
</head>
<body>
<div id="div1">The text above has been created dynamically.</div>
</body>
</html>
document.body.onload = addElement;
function addElement () {
// create a new div element
// and give it some content
var newDiv = document.createElement("div");
var newContent = document.createTextNode("Hi there and greetings!");
newDiv.appendChild(newContent); //add the text node to the newly created div.
// add the newly created element and its content into the DOM
var currentDiv = document.getElementById("div1");
document.body.insertBefore(newDiv, currentDiv);
}
创建文本节点
就像使用 .createElement()
方法创建新元素
一样,你也可以使用 .createTextNode()
方法创建新的文本节点
。
- 创建一个段落元素
- 创建一个文本节点
- 将文本节点附加到段落
- 将段落附加到标签
const myPara = document.createElement('p');
const textOfParagraph = document.createTextNode('I am the text for the paragraph!');
myPara.appendChild(textOfParagraph);
document.body.appendChild(myPara);
不过,既然你已经了解了 .textContent
属性,以下代码也会提供完全相同的结果:
const myPara = document.createElement('p');
myPara.textContent = 'I am the text for the paragraph!';
document.body.appendChild(myPara);
因此,与其创建一个新的文本节点,并将其附加到一个元素上,使用 .textContent
属性来更新元素的文本更加快捷方便。
如需了解更多信息,请查看文档:createTextNode() 文档
在其他位置插入 HTML
根据定义,.appendChild()
方法会添加一个元素作为父元素的最后一个子元素
。灵活选择添加子元素的位置?
.insertAdjacentHTML()
方法必须使用两个参数来调用:
- HTML 的位置
- 要插入的 HTML 文本
这个方法的第一个参数可以让我们在四个不同的位置之一插入新的 HTML:
beforebegin
– 插入 HTML 文本作为前一个子元素afterbegin
– 插入 HTML 文本作为第一个子元素beforeend
– 插入 HTML 文本作为最后一个子元素afterend
– 插入 HTML 文本作为后一个子元素
如果相关元素是一个段落标签,上述的四个位置将处于下面的可视化部分:
<!-- beforebegin-出现在段落标签元素之前-->
<p>
<!-- afterbegin-出现在段落标签元素之后,并作为第一个子元素 -->
Existing text/HTML content
<!-- beforeend-出现在段落标签元素结束标记之前,并作为最后一个子项-->
</p>
<!-- afterend-将作为兄弟姐妹项出现在段落标签元素之后 -->
const mainHeading = document.querySelector('#main-heading');
const htmlTextToAdd = '<h2>Skydiving is fun!</h2>';
mainHeading.insertAdjacentHTML('afterend', htmlTextToAdd);
需要注意的一些要点包括:
- 如果 DOM 中已经存在一个元素,并将该元素传递给
.appendChild()
,则.appendChild()
方法会移动它,而不是复制它 - 元素的
.textContent
属性比使用.createTextNode()
方法创建文本节点更经常被用到 .insertAdjacentHTML()
方法的第二个参数必须是文本
,而不能传递一个元素
请查看文档页面,以了解更多信息:insertAdjacentHTML 文档
移除页面内容
移除子元素
我们可以使用 .removeChild()
方法来…猜对了…移除子元素。基本上,它与 .appendChild()
方法完全相反。因此,就像 .appendChild()
方法一样,.removeChild()
方法也需要:
- 一个父元素
- 将要移除的子元素
<parent-element>.removeChild(<child-to-remove>);
这是 MDN 上的 .removeChild()
文档页面:removeChild 文档
.firstChild
和 .firstElementChild
的不同之处在于,.firstElementChild
总是返回第一个元素
,而 .firstChild
则可能返回空白(如果有的话)以保留底层 HTML 源代码的格式。
使用 .removeChild()
方法的缺点(和解决办法!)
就像 .appendChild()
方法一样,.removeChild()
方法也有一个(小小的)缺点。这两种方法都:
- 需要访问父元素才能操作
不过,我们其实并不需要有父元素,因为有一个解决办法!正如我们可以在父元素上调用 .firstElementChild
属性来访问它的第一个元素,每个元素也有一个 .parentElement
属性来引用其父元素!因此,如果我们能够访问将要添加或移除的子元素,就可以使用 .parentElement
属性将“焦点”移动到该元素的父元素。 然后,我们就可以在被引用的父元素上调用 .removeChild()
(或 .appendChild()
)了。
const mainHeading = document.querySelector('h1');
mainHeading.parentElement.removeChild(mainHeading);
这行代码以 mainHeading
变量开头。它调用了 .parentElement
,因此下一个代码的焦点在父元素上
。然后,在父元素上调用 .removeChild()
。最后,mainHeading
本身作为需要从其父元素中移除的元素被传递。
我们可以使用 .remove()
方法来直接移动子元素:
const mainHeading = document.querySelector('h1');
mainHeading.remove();
这是 MDN 上的 .remove() 文档页面:.remove() 文档
设置页面内容样式
在本部分,我们将学习如何使用以下属性和方法来控制页面和元素样式
:
.style.<prop>
.cssText()
.setAttribute()
.className
.classList
CSS 特异性
特异性水平 | CSS规则 |
---|---|
特异性最低 | 样式表中的规则 |
特异性较高 | 标签 <style> 中的规则 |
特异性最高 | 标签样式属性中的规则 |
根据 MDN,“特异性”是指:浏览器用于确定哪个 CSS 属性值与元素最相关
,因此将被应用的方式。
基本上,样式规则越接近元素,它的特异性就越高
。例如,某个元素的样式属性中的规则将覆盖 CSS 样式表中该元素的样式规则。此外还有所使用的选择器类型的特异性,ID的特异性高于类
。MDN 上的特异性
修改元素的样式属性
我们可以使用 .style
属性来访问元素的样式属性!
const mainHeading = document.querySelector('h1');
mainHeading.style.color = 'red';
在使用 .style
属性时,每次只能修改一个 CSS 样式
。这就是为什么先前的代码中有 .style.color = 'red'
,而不只是 .style = 'red'
。
请查看文档页面,以了解更多信息:样式文档
我们可以使用 .style.cssText
属性一次设置多个 CSS 样式
!
const mainHeading = document.querySelector('h1');
mainHeading.style.cssText = 'color: blue; background-color: orange; font-size: 3.5em';
请注意,在使用 .style.cssText
属性时,你要像在样式表中一样编写 CSS 样式;因此,要写 font-size
,而不是 fontSize
。这与使用单独的 .style.<property>
方式有所不同。还有 .style.cssText 将覆盖 .style 属性中已有的任何内容
。
设置元素的属性
还有一种设置元素样式的方法是完全绕过 .style.<property>
和 .style.cssText
属性,而使用 .setAttribute()
方法:
const mainHeading = document.querySelector('h1');
mainHeading.setAttribute('style', 'color: blue; background-color: orange; font-size: 3.5em;');
请查看文档页面,以了解更多信息:样式文档
.setAttribute()
方法不仅可以设置页面元素的样式
。你还可以使用该方法来设置元素的任何属性
。
const mainHeading = document.querySelector('h1');
// 添加一个 ID 到标题的兄弟元素
mainHeading.nextElementSibling.setAttribute('id', 'heading-sibling');
// 使用新添加的 ID 来访问该元素
document.querySelector('#heading-sibling').style.backgroundColor = 'red';
最后两行可以合并成一行,以绕过设置 ID,而直接设置元素样式:
mainHeading.nextElementSibling.style.backgroundColor = 'red';
访问元素的类
.className
属性,该属性会返回元素所有类的字符串
。我们可以使用 .className
来访问类列表:
<h1 id="main-heading" class="ank-student jpk-modal">Learn Web Development at Udacity</h1>
const mainHeading = document.querySelector('#main-heading');
// 将类的列表存储在一个变量中
const listOfClasses = mainHeading.className;
// 打印出字符串 "ank-student jpk-modal"
console.log(listOfClasses);
.className
属性会返回一个有空格的类字符串
。不过,我们可以使用 JavaScript 字符串方法 .split()
将这个有空格的字符串转换为一个数组:
const arrayOfClasses = listOfClasses.split(' ');
// 打印出字符串数组 ["ank-student", "jpk-modal"]
console.log(arrayOfClasses);
现在,借助这个类数组,我们可以进行任何大规模的数据计算:
- 使用
for
循环遍历类名列表 - 使用
.push()
向列表中添加项目 - 使用
.pop()
从列表中移除项目
.className
是一个属性,因此我们可以通过给该属性赋一个字符串来设置它的值
:
mainHeading.className = "im-the-new-class";
以上代码会抹掉元素的 class 属性中原有的任何类
,并将其替换为
单个类im-the-new-class
。
由于 .className
会返回一个字符串,因此很难添加或移除单个类。让我们来使用新的 .classList
属性吧。.classList
是替代 element.className
作为空格分隔的字符串访问元素的类列表的一种方便的方法。返回一个元素的类属性的实时 DOMTokenList
集合。查看 classList 文档
const mainHeading = document.querySelector('#main-heading');
// 将类的列表存储在一个变量中
const listOfClasses = mainHeading.classList;
// 打印出 ["ank-student", "jpk-modal"]
console.log(listOfClasses);
.classList
属性拥有自己的一些属性,其中一些最常用的是:
.add()
- 向列表中添加类.remove()
- 从列表中移除类.toggle()
- 如果某个类尚不存在,则向列表中添加它;如果某个类已经存在,则从列表中移除它.contains()
- 根据该类是否存在于列表中返回一个布尔值
更多地使用 .classList
属性,它是目前为止这些技能中最有用的属性,而且它可以帮助你将 CSS 样式与 JavaScript 代码保持分开。