30天JavaScript: 文档对象模式(DOM)讲解(Day 21)

244 阅读6分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第30天,点击查看活动详情 

翻译自github专栏

Day 21

文档对象模式(DOM)

HTML文档的结构为JavaScript对象,每个HTML元素都有不同的属性,使得我们可以对其进行不同操作。可以使用JavaScript获取、创建、添加或删除HTML元素。下面的示例。用JavaScript选择HTML元素类似于选择使用CSS。要使用某个HTML元素,我们使用标签名称,ID,样式名或其他属性。

获取元素

我们可以使用JavaScript访问已经创建的单个元素或者多个元素。有不同的方法获取元素。下面的代码有四个h1元素。让我们看看访问h1元素的不同方法。

<!DOCTYPE html>
  <html lang="en">
    <head>
      <title>Document Object Model</title>
    </head>
    <body>

     <h1 class='title' id='first-title'>First Title</h1>
     <h1 class='title' id='second-title'>Second Title</h1>
     <h1 class='title' id='third-title'>Third Title</h1>
     <h1></h1>

    </body>
  </html>

通过标签获取元素

getElementsByTagName():接受一个string类型的标签名称作为参数,返回HTMLCollection对象。HTMLCollection是一html元素类似数组的对象,其中length属性可以获取HTMLCollection对象的大小,当获取到该对象后,我们一般都是通过index直接访问指定元素,或者通过循环,来获取指定的元素,他不支持array的所有API,所以我们用正常的for i循环不用forEach方法

// syntax
document.getElementsByTagName('tagname')
const allTitles = document.getElementsByTagName('h1')

console.log(allTitles) //HTMLCollections
console.log(allTitles.length) // 4

for (let i = 0; i < allTitles.length; i++) {
  console.log(allTitles[i]) // prints each elements in the HTMLCollection
}

通过classname样式名称获取元素

getElementsByClassName() 同样返回HTMLCollection对象. 和上面方法一致

//syntax
document.getElementsByClassName('classname')
const allTitles = document.getElementsByClassName('title')

console.log(allTitles) //HTMLCollections
console.log(allTitles.length) // 4

for (let i = 0; i < allTitles.length; i++) {
  console.log(allTitles[i]) // prints each elements in the HTMLCollection
}

通过id获取元素

getElementsById() 返回单个HTML元素,正因为返回单个,所以要求id必须唯一。定义的时候id前面要加上#

//syntax
document.getElementById('id')
let firstTitle = document.getElementById('first-title')
console.log(firstTitle) // <h1>First Title</h1>

通过querySelector 方法获取元素对象

document.querySelector 可以通过tag,id,classname获取元素对象

querySelector: 可以通过tag,id,class用来获取元素,返回第一个获取到的元素

let firstTitle = document.querySelector('h1') // 查找第一个存在的 tag为h1的 元素
let firstTitle = document.querySelector('#first-title') // 查找id为 first-title 的元素
let firstTitle = document.querySelector('.title') //通过class的名称获取元素

querySelectorAll: 顾名思义和上面不同的是,这个方法返回所有满足条件的元素,参数只能是标签名称tag, 或者class样式名称,返回一个nodeList的数组,支持array的方法。我们可以用for循环,或者forEach都可以遍历nodeList元素数组

const allTitles = document.querySelectorAll('h1') # 查找页面中所有的h1元素

console.log(allTitles.length) // 4
for (let i = 0; i < allTitles.length; i++) {
  console.log(allTitles[i])
}

allTitles.forEach(title => console.log(title))
const allTitles = document.querySelectorAll('.title') // 所用使用到相同class的元素都会返回

添加属性

在HTML的开始标记中添加了属性,该属性提供了元素的其他信息,常用的属性包括:id, class, src, style, href,disabled, title, alt,我们在第四个标题中添加id和classname属性

const titles = document.querySelectorAll('h1')
titles[3].className = 'title'
titles[3].id = 'fourth-title'

通过 setAttribute方法,添加属性

 setAttribute() 方法可以设置任何html的属性. 接受两个参数,属性类型,和属性名称 ,同样利用该方法在第四个标题上添加class和id属性

const titles = document.querySelectorAll('h1')
titles[3].setAttribute('class', 'title')
titles[3].setAttribute('id', 'fourth-title')

不使用 setAttribute添加属性

我们可以使用普通对象设置方法来设置属性,但这种方式不能适用于所有元素。有些属性是DOM对象属性,可以直接设置。例如实例id和class。

//another way to setting an attribute
titles[3].className = 'title'
titles[3].id = 'fourth-title'

添加class 通过classList方法

classList.add方法可以用来给元素添加多个属性. 不会覆盖之前的属性,添加额外属性。

//另一个方法添加class,不会覆盖原来的class
titles[3].classList.add('title', 'header-title')

remove方法移除样式属性

和添加样式属性很像,我们通过classList.remove方法移除样式属性

titles[3].classList.remove('title', 'header-title')

添加文本到院上上

一段由开始标签、结束标签和文本内容共同构成的HTML代码块 可以通过属性textContent或*innerHTML添加文本内容。

通过textContent添加

textContent 属性用于添加文本节点

const titles = document.querySelectorAll('h1')
titles[3].textContent = 'Fourth Title'

通过innerHTML添加文本节点

很多人会对 textContentinnerHTMl 两个方法搞混淆,区别就是innerHTML可以添加文本,HTML元素作为子元素,甚至多个元素。而textContent只能添加文本

Text Content

我们给 textContent 属性赋值文本

const titles = document.querySelectorAll('h1')
titles[3].textContent = 'Fourth Title'
Inner HTML

当我们想要替换父元素的子内容或将其替换为全新的子内容时,我们使用innerHTML属性。接受的值是一个HTML元素字符串

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>JavaScript for Everyone:DOM</title>
  </head>
  <body>
    <div class="wrapper">
        <h1>Asabeneh Yetayeh challenges in 2020</h1>
        <h2>30DaysOfJavaScript Challenge</h2>
        <ul></ul>
    </div>
    <script>
    const lists = `
    <li>30DaysOfPython Challenge Done</li>
            <li>30DaysOfJavaScript Challenge Ongoing</li>
            <li>30DaysOfReact Challenge Coming</li>
            <li>30DaysOfFullStack Challenge Coming</li>
            <li>30DaysOfDataAnalysis Challenge Coming</li>
            <li>30DaysOfReactNative Challenge Coming</li>
            <li>30DaysOfMachineLearning Challenge Coming</li>`
  const ul = document.querySelector('ul')
  ul.innerHTML = lists
    </script>
  </body>
</html>

innerHTML属性同样可以移除所有父类的子元素来替代removeChild()方法。我推荐下面使用的innerHTML属性。

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>JavaScript for Everyone:DOM</title>
  </head>
  <body>
    <div class="wrapper">
        <h1>Asabeneh Yetayeh challenges in 2020</h1>
        <h2>30DaysOfJavaScript Challenge</h2>
        <ul>
            <li>30DaysOfPython Challenge Done</li>
            <li>30DaysOfJavaScript Challenge Ongoing</li>
            <li>30DaysOfReact Challenge Coming</li>
            <li>30DaysOfFullStack Challenge Coming</li>
            <li>30DaysOfDataAnalysis Challenge Coming</li>
            <li>30DaysOfReactNative Challenge Coming</li>
            <li>30DaysOfMachineLearning Challenge Coming</li>
        </ul>
    </div>
    <script>
  const ul = document.querySelector('ul')
  ul.innerHTML = ''
    </script>
  </body>
</html>

添加style样式

添加style样式的颜色值

为标题添加一些风格。如果元素有偶数索引,设置为绿色,否则给它设置为红色。

const titles = document.querySelectorAll('h1')
titles.forEach((title, i) => {
  title.style.fontSize = '24px' // 所有title的字体大小都是24px
  if (i % 2 === 0) {
    title.style.color = 'green'
  } else {
    title.style.color = 'red'
  }
})

添加BackgroundColor属性

如果元素为第偶数个,设置为绿色背景,否则设置为红色背景。

const titles = document.querySelectorAll('h1')
titles.forEach((title, i) => {
  title.style.fontSize = '24px' //所有title的字体大小都是24px
  if (i % 2 === 0) {
    title.style.backgroundColor = 'green'
  } else {
    title.style.backgroundColor = 'red'
  }
})

添加字体大小样式

如果元素为第偶数个,设置为20px大小,否则舌害为30px

Let us add some style to our titles. If the element has even index we give it 20px else 30px

const titles = document.querySelectorAll('h1')
titles.forEach((title, i) => {
  title.style.fontSize = '24px' // all titles will have 24px font size
  if (i % 2 === 0) {
    title.style.fontSize = '20px'
  } else {
    title.style.fontSize = '30px'
  }
})

练习

练习: Level 1

  1. 创建index.html文件,加入4个p元素,通过document.querySelector(tagname) 方法获取所有元素 
  2. document.querySelector('#id') 方法通过设置id来获取每个元素
  3. 获取p元素数组nodeList 通过使用 document.querySelectorAll(tagname) 方法
  4. 循环nodeList数组获取每个p元素的文本节点
  5. 将第四个p元素的文本设置成为:Fourth Paragraph
  6. 使用不同的属性设置方法为所有p标签设置id和class属性

练习: Level 2

  1. 使用JavaScript更改每个段落的样式(例如颜色、背景、边框、字体大小、什么字体等)
  2. 循环遍历每个元素,第1和3个元素设置为绿色,第2和4个元素设置为红色
  3. 给每个标签设置文本, id 和 class

练习: Level 3

DOM: Mini project 1

开发以下应用程序,使用以下HTML元素作为开头。您将在starter文件夹中获得相同的代码。仅使用JavaScript实现所有样式和功能。

-   year的颜色每秒变化一次
-   date 和 time 背景每秒变化一次
-   设置这个项目背景为绿色
-   继续改变颜色为黄色
-   最后改为红色
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
  <head>
    <title>JavaScript for Everyone:DOM</title>
  </head>
  <body>
    <div class="wrapper">
        <h1>Asabeneh Yetayeh challenges in 2020</h1>
        <h2>30DaysOfJavaScript Challenge</h2>
        <ul>
            <li>30DaysOfPython Challenge Done</li>
            <li>30DaysOfJavaScript Challenge Ongoing</li>
            <li>30DaysOfReact Challenge Coming</li>
            <li>30DaysOfFullStack Challenge Coming</li>
            <li>30DaysOfDataAnalysis Challenge Coming</li>
            <li>30DaysOfReactNative Challenge Coming</li>
            <li>30DaysOfMachineLearning Challenge Coming</li>
        </ul>
    </div>
  </body>
</html>

image.png

image.png