第七章DOM 7.2 JavaScript DOM 操作

288 阅读13分钟

7.2 获取 DOM 元素

getElementById

document.getElementById()可以通过元素的 ID 属性获取对应的 DOM 元素。 使用方法如下: var element = document.getElementById(id); 其中,id 为要获取的元素的 ID 属性的值。getElementById()方法返回一个元素对象,可以用来操作该元素,比如修改其内容或样式,绑定事件等。 例如,假设我们有以下 HTML 代码: <div id="myDiv">This is my div element.</div> 我们可以使用 getElementById()方法获取这个元素,并修改它的内容和背景颜色:

var myDiv = document.getElementById('myDiv');
myDiv.innerHTML = 'This is my updated div element.';
myDiv.style.backgroundColor = 'red';

上述代码中,首先通过 getElementById()方法获取了 ID 为 myDiv 的元素对象,并保存在 myDiv 变量中。然后,修改了这个元素的内容和背景颜色。 注意点 1: 我们应该让页面中元素的 id 是唯一的,即使不唯一也不会报错,但是 getElementById 方法获取到的是第一个匹配的元素。 注意点 2: 在用 JavaScript 获取 DOM 元素的时候,一定要保证 DOM 元素已经存在,所以要保证 script 标签在 DOM 元素的后面,之后的方法也是类型。

getElementsByTagName

getElementsByTagName()可以通过元素标签名获取对应的 DOM 元素。 使用方法如下: var elements = document.getElementsByTagName(tagName); 其中,tagName 为要获取的元素的标签名,比如 div、p、ul 等。getElementsByTagName()方法返回一个元素对象数组,可以用来操作这些元素,比如修改它们的内容或样式,绑定事件等。 例如,假设我们有以下 HTML 代码:

<p>This is the first paragraph.</p>
<p>This is the second paragraph.</p>

我们可以使用 getElementsByTagName()方法获取所有的

元素,并修改它们的内容和颜色:

var paragraphs = document.getElementsByTagName('p');
for (var i = 0; i < paragraphs.length; i++) {
  paragraphs[i].innerHTML = 'This is a paragraph.';
  paragraphs[i].style.color = 'blue';
}

上述代码中,首先通过 getElementsByTagName()方法获取所有的

元素,并保存在 paragraphs 数组中。然后,使用一个循环遍历这些元素,将它们的内容修改为"This is a paragraph.",并将它们的颜色修改为蓝色。

getElementsByClassName

getElementsByClassName 方法是 document 对象的一个方法,用于根据指定的类名获取当前文档中所有符合条件的元素节点,返回的是一个类数组对象,其中每个元素都是一个元素节点对象。 该方法的语法如下: document.getElementsByClassName(className); 其中,className 是一个字符串,表示要获取元素节点的类名,可以指定一个或多个类名,多个类名之间用空格隔开。 例如,要获取所有类名为 box 的元素节点,可以使用以下代码:

<!DOCTYPE html>
<html>
  <head>
    <title>getElementsByClassName</title>
    <style type="text/css">
      .box {
        width: 100px;
        height: 100px;
        background-color: red;
        margin: 10px;
      }
    </style>
  </head>
  <body>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <script type="text/javascript">
      var boxes = document.getElementsByClassName('box');
      console.log(boxes); // 返回一个类数组对象
      console.log(boxes.length); // 5
    </script>
  </body>
</html>

在上面的例子中,getElementsByClassName 方法返回一个类数组对象,其中包含了文档中所有类名为 box 的元素节点。通过 boxes.length 可以获取到符合条件的元素节点个数,也可以通过下标来访问某一个具体的元素节点。 可以指定多个类名来查找元素,这时需要将多个类名用空格分隔。例如,如果我们想获取类名既为 box 又为 red 的元素节点,可以这样写:

<!DOCTYPE html>
<html>
  <head>
    <title>getElementsByClassName with multiple class names</title>
    <style type="text/css">
      .box {
        width: 100px;
        height: 100px;
        background-color: red;
        margin: 10px;
      }
      .red {
        background-color: red;
      }
      .blue {
        background-color: blue;
      }
    </style>
  </head>
  <body>
    <div class="box red"></div>
    <div class="box blue"></div>
    <div class="box red"></div>
    <div class="box"></div>
    <div class="box red blue"></div>
    <script type="text/javascript">
      var boxes = document.getElementsByClassName('box red');
      console.log(boxes); // 返回一个类数组对象
      console.log(boxes.length); // 3
    </script>
  </body>
</html>

在上面的例子中,我们在<div>元素中同时添加了 box 和 red 类名,这样这个元素就同时符合这两个类名的条件了。我们调用 document.getElementsByClassName('box red')方法就可以获取到所有同时包含 box 和 red 类名的元素节点了。 querySelector querySelector 方法是 document 对象的一个方法,用于在文档中查找符合指定 CSS 选择器的第一个元素节点,返回的是一个元素节点对象。 该方法的语法如下: document.querySelector(selector); 其中,selector 是一个 CSS 选择器,表示要查找的元素节点的样式。selector 可以是任何符合 CSS 规则的字符串,例如标签名、类名、ID 等。下面是使用 querySelector 配合 css 选择器的例子:

<!DOCTYPE html>
<html>
  <head>
    <title>querySelector demo</title>
  </head>
  <body>
    <div id="main">
      <div class="box">1</div>
      <div class="box">2</div>
      <div class="box">3</div>
      <div class="box">4</div>
      <div class="box">5</div>
    </div>
    <script type="text/javascript">
      // 选择第一个类名为box的div元素节点对象
      var box1 = document.querySelector('.box');
      console.log(box1.innerHTML); // 1

      // 选择#main元素节点下的第一个类名为box的div元素节点对象
      var box2 = document.querySelector('#main .box');
      console.log(box2.innerHTML); // 1

      // 选择#main元素节点下第一个类名为box的div元素节点对象
      var box3 = document.querySelector('#main .box:first-child');
      console.log(box3.innerHTML); // 1

      // 选择#main元素节点下奇数位置的第一个类名为box的div元素节点对象
      var box4 = document.querySelector('#main .box:nth-child(odd)');
      console.log(box4.innerHTML); // 1

      // 选择#main元素节点下偶数位置的第一个类名为box的div元素节点对象
      var box5 = document.querySelector('#main .box:nth-child(even)');
      console.log(box5.innerHTML); // 2

      // 选择#main元素节点下偶数位置的第三个类名为box的div元素节点对象
      var box5 = document.querySelector('#main .box:nth-child(3)');
      console.log(box5.innerHTML); // 3
    </script>
  </body>
</html>

querySelectorAll

querySelectorAll 方法和 querySelector 方法类似,但是它会返回匹配指定选择器的所有元素,而不是只返回第一个匹配的元素。 querySelectorAll 方法的语法如下: elementList = parentNode.querySelectorAll(selectors); 注意点: 这里和之前的写法不一样了,把 document 改成了 parentNode,document 其实也是一个 parentNode。所以我们可以知道其实不仅仅是 document 有 querySelectorAll 方法,其他普通的 dom 节点也可以调用这个方法,不同的就是查询的范围,document 是在整个 dom 树上查找,而使用 parentNode 查找则是在其子元素内查找。 请看一下例子:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="main">
      <div class="box"><p></p></div>
      <div class="box"></div>
      <div class="box special"><p>special p</p></div>
      <div class="box"></div>
      <div class="box special"></div>
    </div>
    <script>
      var boxes = document.querySelectorAll('.box');
      console.log(boxes.length); // 5

      var specialBoxes = document.querySelectorAll('#main .box.special');
      console.log(specialBoxes.length); // 2

      var pInspecialBox = specialBoxes[0].querySelectorAll('p');
      console.log(pInspecialBox[0].innerHTML); // special p
    </script>
  </body>
</html>

设置元素属性的方法

setAttribute() 是 JavaScript 中用于设置元素属性的方法。它接受两个参数,第一个参数是要设置的属性名称,第二个参数是要设置的属性值。下面是该方法的详细使用说明: 语法 element.setAttribute(name, value); 参数

  1. name: 要设置的属性名称,必须是一个字符串。如果该属性不存在,则会创建一个新的属性,并将其添加到元素中。
  2. value: 要设置的属性值,可以是任何字符串。如果该属性已经存在,则会将其值设置为提供的值。如果该属性不存在,则会创建一个新的属性,并将其值设置为提供的值。

示例

假设您有一个 <img> 元素,其 src 属性为空。要将 src 属性设置为 "image.jpg",可以使用以下代码:

var img = document.querySelector("img");
img.setAttribute("src", "image.jpg");

这将把 <img> 元素的 src 属性设置为 "image.jpg"。如果该属性已经存在,则该方法将更新其值。如果该属性不存在,则该方法将创建一个新的属性,并将其添加到元素中。

注意事项

  • 如果要将属性值设置为 null 或 undefined,则会将属性值设置为空字符串。
  • 如果要将属性值设置为对象或函数,则会将其自动转换为字符串。
  • 有些属性不能使用 setAttribute() 方法来设置,例如 style 属性和事件处理程序属性,这些属性需要使用特殊的语法来设置,后边会单独讲解。

下面列举介绍一些常见的属性:

  • class 属性 class 属性用于设置元素的 CSS 类。例如,要将一个元素的类设置为 "my-class",可以使用以下代码: element.setAttribute("class", "my-class"); 这将会给元素添加一个名为 "my-class" 的 CSS 类。如果元素之前已经有其他的 CSS 类,这个类将被添加到它们的后面,多个类名之间使用空格分隔。
  • id 属性 id 属性用于设置元素的 ID。例如,要将一个元素的 ID 设置为 "my-element",可以使用以下代码: element.setAttribute("id", "my-element"); 这将会将元素的 ID 设置为 "my-element"。一个 HTML 文档中只能有一个 ID 为 "my-element" 的元素,如果已经有了一个这样的元素,那么这个方法将会替换它的 ID。
  • src 属性 src 属性用于设置图片或其他媒体文件的 URL。例如,要将一个图片元素的 src 属性设置为 "image.jpg",可以使用以下代码: element.setAttribute("src", "image.jpg"); 这将会设置图片元素的 src 属性为 "image.jpg"。如果这个元素之前已经有了一个 src 属性,这个方法将会替换它的值。
    1. href 属性 href 属性用于设置链接的 URL。例如,要将一个链接元素的 href 属性设置为"www.example.com",可以使用以下代码: element.setAttribute("href", "https://www.example.com"); 这将会设置链接元素的 href 属性为 "错误!超链接引用无效。 href 属性,这个方法将会替换它的值。
    1. alt 属性 alt 属性用于设置图片元素的替代文本。例如,要将一个图片元素的 alt 属性设置为 "My image",可以使用以下代码: element.setAttribute("alt", "My image"); 这将会设置图片元素的 alt 属性为 "My image"。如果这个元素之前已经有了一个 alt 属性,这个方法将会替换它的值。

元素内容的设置和获取

在 JavaScript 中,textContent 、innerText、innerHTML 、和 outerHTML 都是用于获取或设置元素内容的属性,但它们之间有一些区别:

  • textContent: 返回元素中包含的所有文本内容,包括隐藏文本,换行符等,但不包括 HTML 标签。它只会返回文本内容,不会包含任何 HTML 代码。
  • innerText: 返回元素中包含的文本内容,并去除 HTML 标签。它只会返回可见文本,而不会包含任何隐藏文本。innerText 属性在 IE 中被首先引入,然后被其他浏览器实现。
  • innerHTML: 返回元素中包含的 HTML 代码,包括标签和文本。与 innerText 不同,它会将元素的所有内容返回,包括隐藏文本和标签。
  • outerHTML: 是在 innerHTML 的基础上再加上元素本身的 HTML 标签。 看以下例子:
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      div {
        border: 1px solid #000;
        padding: 10px;
      }
    </style>
  </head>
  <body>
    <div id="myDiv">
      <h1>Hello World!</h1>
      <p style="display: none;">This is hidden text.</p>
    </div>
    <script>
      var myElement = document.getElementById('myDiv');
      console.log('textContent:', myElement.textContent);
      console.log('innerText:', myElement.innerText);
      console.log('innerHTML:', myElement.innerHTML);
      console.log('outerHTML:', myElement.outerHTML);
    </script>
  </body>
</html>

在浏览器调试窗口的输出如下:

同时也可以给 textContent 、innerText、innerHTML 、和 outerHTML 属性就行赋值操作,设置元素的内容。 看以下例子:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      div {
        border: 1px solid #000;
        padding: 10px;
      }
    </style>
  </head>
  <body>
    <p>textContent</p>
    <div id="textContent"></div>
    <p>innerText</p>
    <div id="innerText"></div>
    <p>innerHTML</p>
    <div id="innerHTML"></div>
    <p>outerHTML</p>
    <div id="outerHTML"></div>
    <script>
      var textContentDom = document.getElementById('textContent');
      textContentDom.textContent = `<h1>Hello World!</h1>
    <p style="display: none;">This is 
    hidden text.</p>`;

      var innerTextDom = document.getElementById('innerText');
      innerTextDom.innerText = `<h1>Hello World!</h1>
    <p style="display: none;">This is 
    hidden text.</p>`;

      var innerHTMLDom = document.getElementById('innerHTML');
      innerHTMLDom.innerHTML = `<h1>Hello World!</h1>
    <p style="display: none;">This is 
    hidden text.</p>`;

      var outerHTMLDom = document.getElementById('outerHTML');
      outerHTMLDom.outerHTML = `<h1>Hello World!</h1>
    <p style="display: none;">This is 
    hidden text.</p>`;
    </script>
  </body>
</html>

页面上得到的结果如下:

可以看到,设置时的区别:

  1. textContent: 设置时不会解析 HTML 标签和特殊的字符,例如换行符。
  2. innerText: 设置时也不会解析 HTML 标签但是解析了换行符,文本原封不动的展示。
  3. innerHTML: 设置时,浏览器会解析其中的 HTML 代码并创建对应的 DOM 节点。
  4. outerHTML: 设置时,浏览器会解析其中的 HTML 代码并创建对应的 DOM 节点。与 innerHTML 不同的是,outerHTML 设置的内容替换了元素本身的标签。 需要注意 innerHTML 和 outerHTML 都会让浏览器进行解析,存在安全风险,因此应该避免将未经过滤和验证的用户输入作为 HTML 插入到页面中。

修改元素 class

修改元素 class 的方法 1 直接使用上面讲过的 setAttribute 方法 element.setAttribute('class', 'classValue'); 2 设置 className 的属性 element.className = 'classValue'; 3 使用 classList 属性 element.classList 属性是一个 DOMTokenList 对象,它提供了一组方法来添加、删除和切换元素的类。这些方法包括:

  • add(className): 添加一个类到元素的类列表中
  • remove(className): 从元素的类列表中删除一个类
  • toggle(className): 如果元素的类列表中存在指定的类,则删除它;否则添加它
  • contains(className): 检查元素的类列表中是否包含指定的类 示例代码:
let element = document.getElementById("myElement");
element.classList.add("myClass");
element.classList.remove("myClass");
element.classList.toggle("myClass");
console.log(element.classList.contains("myClass"));

通过例子可以看出来,直接设置 class 属性和使用 className 属性是相同的,都是直接操作整个 class 的取值,而当一个元素有多个 class 值共同存在的时候 classList 则功能更强大,帮我们封装好了一些方法。

修改元素 style 的方法

在 JavaScript 中,可以通过以下方法修改元素的 style 属性:

  1. 使用 element.style.property = value 形式来设置单个 CSS 属性的值。其中,element 是元素节点,property 是 CSS 属性名称(驼峰式命名),value 是 CSS 属性的值。例如:
   // 获取一个 id 为“myDiv”的元素节点
   var myDiv = document.getElementById("myDiv");
   // 设置元素节点的背景颜色为红色
   myDiv.style.backgroundColor = "red";
   // 设置元素节点的字体大小为 16 像素
   myDiv.style.fontSize = "16px";
  1. 使用 element.setAttribute("style", "property: value; property: value; ...") 的方式来设置多个 CSS 属性的值。其中,element 是元素节点,property 是 CSS 属性名称,value 是 CSS 属性的值。多个 CSS 属性之间使用分号进行分隔。例如:
   // 获取一个 id 为“myDiv”的元素节点
   var myDiv = document.getElementById("myDiv");
   // 设置元素节点的背景颜色和字体大小
   myDiv.setAttribute("style", "background-color: red; font-size: 16px;");

需要注意的是,这种方式会覆盖元素的所有样式属性,因此如果只想修改元素的某个样式属性,最好使用方法 1。此外,由于使用 setAttribute() 方法设置的 style 属性值是一个字符串,因此在修改时需要谨慎处理,以避免破坏原有的样式。

操作元素

创建元素

createElement(tagName) 创建一个指定标签名的新元素节点。

const div = document.createElement('div');

createTextNode(text) 创建一个包含指定文本内容的新文本节点。

const textNode = document.createTextNode('Hello World!');

createDocumentFragment() createDocumentFragment()方法可以用来创建一个空的文档片段节点。文档片段节点是一种特殊类型的节点,它可以包含其他节点,但是它本身并不在文档树中占有位置,因此创建文档片段节点可以提高 DOM 操作的性能,特别是需要频繁操作 DOM 时。 下面是一个使用 createDocumentFragment()方法的示例代码,它创建了一个包含多个子节点的文档片段,并将该文档片段插入到文档树中:

// 创建一个文档片段
var fragment = document.createDocumentFragment();

// 创建多个子节点
var p1 = document.createElement("p");
p1.textContent = "这是第一个段落。";
fragment.appendChild(p1);

var p2 = document.createElement("p");
p2.textContent = "这是第二个段落。";
fragment.appendChild(p2);

var img = document.createElement("img");
img.src = "example.png";
fragment.appendChild(img);

// 将文档片段插入到文档树中
var container = document.getElementById("container");
container.appendChild(fragment);

在这个示例中,首先使用 createDocumentFragment()方法创建了一个空的文档片段节点,然后使用 createElement()方法创建了多个子节点,并使用 appendChild()方法将它们添加到文档片段中。最后,使用 appendChild()方法将文档片段节点插入到文档树中的容器元素中。这个示例演示了如何使用文档片段节点来批量添加节点,从而提高 DOM 操作的性能。

插入元素

appendChild(child) 将一个子元素节点添加到父元素节点的末尾。

const parent = document.querySelector('#parent');
const child = document.createElement('div');
parent.appendChild(child);

insertBefore(newNode, refNode)

将一个新元素节点插入到参考元素节点的前面。

const parent = document.querySelector('#parent');
const newChild = document.createElement('div');
const refChild = document.querySelector('.ref');
parent.insertBefore(newChild, refChild);

删除元素

removeChild(child) 从父元素节点中移除一个子元素节点。

const parent = document.querySelector('#parent');
const child = document.querySelector('#child');
parent.removeChild(child);

注意:在删除元素节点之前,需要先获取到它的父元素节点。

替换元素

replaceChild 和 cloneNode 是 JavaScript 中用于操作 DOM 树的方法。 replaceChild 方法用于替换父元素中的子元素。它需要两个参数:新的子元素和要被替换的旧的子元素。例如:

var parent = document.getElementById("parent");
var newChild = document.createElement("p");
var oldChild = document.getElementById("old-child");
parent.replaceChild(newChild, oldChild);

这将用新的<p>元素替换旧的子元素。

克隆元素

cloneNode 方法用于克隆元素。它接受一个布尔值参数,表示是否要克隆元素的子元素。例如:

var original = document.getElementById("original");
var clone = original.cloneNode(true);

这将克隆 original 元素及其所有子元素,并将其存储在 clone 变量中。需要注意的是,cloneNode 方法只复制元素的属性和节点值,而不会复制事件监听器或附加到元素上的任何数据。如果需要复制事件监听器或其他数据,需要手动添加到克隆的元素上。 下面再举一个设置克隆子元素和不克隆子元素的例子:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div id="original">
    <p>这是一个段落。</p>
    <ul>
      <li>列表项1</li>
      <li>列表项2</li>
      <li>列表项3</li>
    </ul>
  </div>
  <script>
    // 获取原始元素
    var original = document.getElementById("original");
    // 克隆元素
    var deepClone = original.cloneNode(true);
    // 修改克隆元素的属性
    deepClone.id = "deepClone";
    deepClone.getElementsByTagName("p")[0].innerHTML = "这是一个克隆的段落。";
    // 将克隆元素添加到文档中
    document.body.appendChild(deepClone);

    // 克隆元素
    var shallowClone = original.cloneNode();
    // 修改克隆元素的属性
    shallowClone.id = "shallowClone";
    shallowClone.textContent = shallowClone.getElementsByTagName("p").length;
    document.body.appendChild(shallowClone);

  </script>  
</body>
</html>

页面上的展现截图如下:

可以看到当不克隆子元素时,会只克隆元素本身。