JS DOM 常用节点操作 (上)

关联:

JS DOM 常用节点操作(下)

目录

DOM 概念

DOM 操作

条件查找

1. 根据 id 属性查找元素

2. 根据元素类型查找元素

3. 根据 class 属性查找元素

4. 根据选择器查找第一个命中的元素

5. 根据选择器查找全部命中的元素

6. 查找页面根元素或Body元素

爬树查找

1. 查找父节点

2. 查找子节点 - 元素节点、注释节点、文本节点

3. 查找子节点 - 元素节点

4. 获取第一个和最后一个节点

5. 查找前一个兄弟节点

6. 查找后一个兄弟节点

添加节点

移除节点

复制节点

操作元素值

操作元素属性


DOM 概念

将 HTML 文档中的标签、标签属性、标签文本转换为一个个对象, 并按照标签之间的关系, 将这些对象以树形结构的形式保存在内存中, 然后可以用操作对象的方式对实际元素进行修改。

DOM树:

DOM 操作

条件查找

根据条件进行查找 如, 想查找某个类型的元素、查找指定 ID 的元素、查找使用了指定样式的元素等,条件查找时,返回的都是 HTMLElement 对象( Node对象的子类 )

1. 根据 id 属性查找元素

<body>
<div id='container'></div>
<script>
  document.getElementById('container')
</script>
</body>

2. 根据元素类型查找元素

<body>
<div></div>
<div></div>
<script>
  let elementArray = document.getElementsByTagName('div')
  for(let i = 0 ; i < elementArray.length; i++){
    elementArray[i].innerText = `我是第${i + 1}个div`
  }
</script>
</body>

3. 根据 class 属性查找元素

<body>
<style>
  .font-red {
    color: red;
  }
</style>
<div class="font-red"></div>
<div class="font-red"></div>
<script>
  let elementArray = document.getElementsByClassName('font-red')
  for (let i = 0; i < elementArray.length; i++) {
    elementArray[i].innerText = `我是第${i + 1}个div`
  }
</script>
</body>

4. 根据选择器查找第一个命中的元素

<body>
<div></div>
<p class="font-red"></p>
<div class="font-red"></div>
<script>
  // 使用标签选择器
  console.dir(document.querySelector('div'))
  // 使用类选择器
  console.dir(document.querySelector('.font-red'))
  // 使用更详细的类选择器
  console.dir(document.querySelector('div.font-red'))
</script>
</body>

5. 根据选择器查找全部命中的元素

<body>
<div></div>
<div></div>
<script>
  let elementArray = document.querySelectorAll('div')
  for (let i = 0; i < elementArray.length; i++) {
    elementArray[i].innerText = `我是第${i + 1}个div`
  }
</script>
</body>

6. 查找页面根元素或Body元素

<script>
  // 获取 body 元素
  console.dir(document.body)
  // 获取根元素
  console.dir(document.documentElement)
  
  // 不同浏览器或浏览器版本,在获取滚动条的滚动距离时,可能会有兼容问题
  // 解决兼容问题
  let scrollTop = document.body.scrollTop || document.documentElement.scrollTop
</script>

爬树查找

按照树形结构中的关系进行查找, 如, 父节点、子节点、兄弟节点等,爬树查找时,返回的都是 Node 对象。

DOM 树的节点有不同的类型, Node 对象中由 nodeType 属性对其类型进行区分

常见的节点类型有:

节点类型nodeTypenodeNamenodeValue
元素节点1元素名null/undefined
属性节点2属性名属性值
文字节点3text文本内容
注释节点8comment注释内容

1. 查找父节点

<body>
<div id="grandpa">
  <div id="parent">
    <div id="inner"></div>
  </div>
</div>
<script>
  let innerDiv = document.querySelector('#inner')
  console.log(innerDiv.parentNode)
</script>
</body>

2. 查找子节点 - 元素节点、注释节点、文本节点

<body>
<div id="outer">
  文本<!-- 注释节点 -->
  <div id="son">节点值
    <div id="grandson"></div>
  </div>
</div>
<script>
  let innerDiv = document.querySelector('#outer')
  let children = innerDiv.childNodes
  console.log(`一共有${children.length}个子节点`)
  for (let i = 0; i < children.length; i++) {
    console.log(`第${i + 1}个节点, 节点名为:${children[i].nodeName}`)
    console.log(`第${i + 1}个节点, 节点类型为:${children[i].nodeType}`)
    console.log(`第${i + 1}个节点, 节点值为:${children[i].nodeValue}`)
  }
  /**
   * 第一个节点: 是文本节点,既 <div id="outer"> 后的 换行符 + 空格 + 文本
   * 第二个节点: 是注释节点,既 <!-- 注释节点 -->
   * 第三个节点: 是文本节点,既 <!-- 注释节点 --> 后的 换行符 + 空格
   * 第四个节点: 是元素节点,既 <div id="son"> </div> 部分
   * 第五个节点: 是文本节点,既 <div id="son"> </div> 后的 换行符
   */
</script>
</body>

3. 查找子节点 - 元素节点

<body>
<div id="outer">
  文本<!-- 注释节点 -->
  <div id="son">
    <div id="grandson"></div>
  </div>
</div>
<script>
  let innerDiv = document.querySelector('#outer')
  // 只获取元素节点,既 <div id="son"> </div> 部分
  let children = innerDiv.children
  console.log(innerDiv.children.length) // 结果:1
  for (let i = 0; i < children.length; i++) {
    console.log(children[i])
  }
</script>
</body>

4. 获取第一个和最后一个节点

<body>
<div id="outer">
  <div id="son"></div>
  <div id="daughter"></div>
</div>
<script>
  let innerDiv = document.querySelector('#outer')

  // 查找第一个和最后一个节点(可能是元素节点、文本节点、注释节点)
  console.log(innerDiv.firstChild)
  console.log(innerDiv.lastChild)

  // 查找第一个和最后一个元素节点查找第一个和最后一个元素节点,有浏览器兼容问题
  console.log(innerDiv.firstElementChild)
  console.log(innerDiv.lastElementChild)

  // 查找第一个和最后一个元素节点,最优方案
  console.log(innerDiv.children[0])
  console.log(innerDiv.children[innerDiv.children.length - 1])
</script>
</body>

5. 查找前一个兄弟节点

<body>
<div id="outer">
  <div id="sibling"></div>
  <div id="current"></div>
</div>
<script>
  /*
   * previousSibling - 查找前一个兄弟节点(文本类型、元素类型、注释类型)
   * previousElementSibling - 查找前一个元素类型的兄弟节点
   */
  let currentDiv = document.querySelector('#current')
  console.log(currentDiv.previousSibling) // 结果: 文本类型节点,既 <div id="sibling"></div> 后的换行和空格
  console.log(currentDiv.previousElementSibling) // 结果: 元素类型节点,既<div id="sibling"></div>
</script>
</body>

6. 查找后一个兄弟节点

<body>
<div id="outer">
  <div id="current"></div>
  <div id="sibling"></div>
</div>
<script>
  /*
   * nextSibling - 查找后一个兄弟节点(文本类型、元素类型、注释类型)
   * nextElementSibling - 查找后一个元素类型的兄弟节点
   */
  let currentDiv = document.querySelector('#current')
  console.log(currentDiv.nextSibling) // 结果: 文本类型节点,既 <div id="current"></div> 后的换行和空格
  console.log(currentDiv.nextElementSibling) // 结果: 元素类型节点,既<div id="sibling"></div>
</script>
</body>

添加节点

1. document.createElement,创建元素对象(只是创建元素对象, 并不会添加到页面)

2. node.appendChild(element),页面添加元素 - 末尾添加

3. node.insertBefore(element, targetElement),页面添加元素 - 添加位置取决于第二个参数

4. createElement 应与 appendChild 或 insertBefore 联合使用

insertBefore 的第二个参数传 null 则在节点末尾添加, 第二个参数传节点对象,则在节点对象前添加

<body>
<div id="container">
  <h2 id="target">中间的元素</h2>
</div>
<script>
  let target = document.getElementById('target')
  let container = document.getElementById('container')

  // 在 container 内 target 前,添加元素
  let before = document.createElement('h2')
  before.innerText = '添加到开头的元素'
  container.insertBefore(before, target)

  // 在 container 的末尾添加元素
  let last = document.createElement('h2')
  last.innerText = '添加到后面的元素'
  container.appendChild(last)
</script>
</body>

移除节点

移除指定元素内的指定节点

<body>
<div id="container">
  <h2 id="target">会被移除的元素</h2>
</div>
<script>
  let target = document.getElementById('target')
  let container = document.getElementById('container')
  container.removeChild(target)
</script>
</body>

复制节点

浅拷贝:实参为 false 或 不传, 只拷贝节点本身, 哪怕下级是文本节点也不会拷贝

<body>
<div id="container">
  <h2 id="target">这是内部节点</h2>
</div>
<script>
  let container = document.querySelector('#container')
  let target = document.querySelector('#target')
  let copy = target.cloneNode()
  // 不会拷贝文本节点, 所以要自己设置文字, 不然画面啥都不显示
  copy.innerText = '这是复制出来的内部节点'
  container.appendChild(copy)
</script>
</body>

深拷贝:实参为 true,拷贝节点本身和下级节点

<body>
<div id="container">
  <h2 id="target">这是内部节点</h2>
</div>
<script>
  let container = document.querySelector('#container')
  let target = document.querySelector('#target')
  let copy = target.cloneNode(true)
  container.appendChild(copy)
</script>
</body>

操作元素值

value:用在表单元素中,设置和获取表单元素的值, 和表单元素中的的 value 属性对应

innerText:设置和获取元素标签对儿中的文字文本, 并会自动忽略文本的前后空格和换行符

innerHTML:设置和获取元素标签对儿中的内容(包括 html 标签),赋值时如果内容为 html 标签,页面则会自动识别成 html 元素

<body>
<!-- innerHtml -->
<div id="innerHTMLCase">
  <h2> 这是 innerHTML 取值 </h2>
</div>
<!-- innerText -->
<div id="innerTextCase">
  <h2> 这是 innerText 取值 </h2>
</div>
<!-- value -->
<input id="valueCase" type="text" value="这是文本框值">

<script>
  /*
   * innerHTML
   */
  let innerHTMLCase = document.querySelector('#innerHTMLCase')
  // 取值
  console.log(innerHTMLCase.innerHTML) // 结果: \n  <h2> 这是 innerHTML 取值 </h2>
  // 赋值
  innerHTMLCase.innerHTML = '<h2 id="target"> 这是 innerHTML 赋值 </h2>' // 画面看效果

  /*
   * innerText
   */
  let innerTextCase = document.querySelector('#innerTextCase')
  // 取值
  console.log(innerTextCase.innerText) // 结果:这是 innerText 取值
  // 赋值
  innerTextCase.innerText = '<h2 id="target"> 这是 innerText 赋值 </h2>' // 画面看效果

  /*
   * value
   */
  let valueCase = document.querySelector('#valueCase')
  // 取值
  console.log(valueCase.value) // 结果:这是文本框值
  // 赋值
  valueCase.value = '这是修改后的文本框值' // 画面看效果
</script>
</body>

操作元素属性

常用操作:

getAttribute ( 属性名 )获取元素属性
setAttribute ( 属性名, 属性值 )设置元素属性
removeAttribute ( 属性名 )删除元素属性
element.className设置和获取元素类名
element.属性名设置和获取元素属性

① 属性操作配合自定义属性

<body>
<div id="defineProp" prop="自定义属性"></div>
<script>
  let defineProp = document.querySelector('#defineProp')
  console.log(defineProp.getAttribute('prop')) // 获取自定义属性值
  defineProp.setAttribute('index', '1') // 设置自定义属性
  defineProp.removeAttribute('prop') // 删除自定义属性
  defineProp.style = 'width: 100px; height: 100px; border: 1px solid black' // 设置元素属性
</script>
</body>

② H5 规范了自定义属性要用 data- 开头,  然后统一从元素对象的 dataset 属性中获取, 获取时不用写 data-

<body>
<div id="singleton" data-singleton="自定义属性, 普通属性名"></div>
<div id="camelCase" data-camel-case="自定义属性, 驼峰属性名"></div>
<script>
  // 普通属性名
  let singleton = document.querySelector('#singleton')
  console.log(singleton.dataset.singleton) // 方式一
  console.log(singleton.dataset['singleton']) // 方式二
  singleton.dataset.no = '1' // 通过 js 也可以为 html 元素设置自定义属性

  // 驼峰属性名
  let camelCase = document.querySelector('#camelCase')
  console.log(camelCase.dataset.camelCase) // 方式一
  console.log(camelCase.dataset['camelCase']) // 方式二

  // 移除属性时, 不能省略 data- 
  camelCase.removeAttribute('data-camel-case')
</script>
</body>

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值