文章目录
1、DOM节点的分类
DOM树里每一个内容都称之为节点,节点分为三种:
- 元素节点:所有的标签,比如 body、div,其中html 是根节点
- 属性节点:所有的属性,比如a标签的href属性
- 文本节点:所有的文本
- 其他
2、查找亲戚节点
这里相比之前的querySelector,是通过元素节点之间的关系,来做查找,这是二者的区别,两种查找并不冲突,而是一种补充,省的去多次querySelector
2.1 父节点查找
parentNode属性,返回最近一级的父节点 ,找不到返回为null
// 语法
子元素.parentNode
示例:
<body>
<div class="dad">
<div class="baby"></div>
</div>
<script>
const baby = document.querySelector('.baby')
console.dir(baby.parentNode)
</script>
</body>
练习:关闭二维码案例
按之前的逻辑,要querySelector分别查找关闭 x 的Dom对象,以及其父元素div,但现在只需获取一次 x 元素,然后直接关闭 x 元素的父元素
<!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>
.box {
position: relative;
width: 1000px;
height: 200px;
background-color: pink;
margin: 100px auto;
text-align: center;
font-size: 50px;
line-height: 200px;
font-weight: 700;
}
.box1 {
position: absolute;
right: 20px;
top: 10px;
width: 20px;
height: 20px;
background-color: skyblue;
text-align: center;
line-height: 20px;
font-size: 16px;
cursor: pointer;
}
</style>
</head>
<body>
<div class="box">
我是二维码
<div class="box1">X</div>
</div>
<script>
const box1 = document.querySelector('.box1')
box1.addEventListener('click', function () {
box1.parentNode.style.display = 'none'
})
</script>
</body>
</html>
再扩展下,现在有三个一模一样的二维码大盒子,它们的类名也一样,这里再querySelector就有问题,三个大盒子都叫box ,但用parentNode就完全不用考虑 ==> 通过关系去查找节点,不要总是无脑querySelector
//...CSS略
<body>
<div class="box">
我是二维码
<div class="box1">X</div>
</div>
<div class="box">
我是二维码
<div class="box1">X</div>
</div>
<div class="box">
我是二维码
<div class="box1">X</div>
</div>
<script>
const box1List = document.querySelectorAll('.box1')
// 这里事件委托不了,它们的父级是三个box,再父级就到body了,那循环遍历绑定
for (let i = 0; i < box1List.length; i++) {
box1List[i].addEventListener('click', function () {
// 这里再querySelector就有问题,三个大盒子都叫box
this.parentNode.style.display = 'none'
})
}
</script>
</body>
</html>
2.2 子节点查找
childNodes属性:
- 作用:获得所有子节点、包括文本节点(空格、换行)、注释节点等,不常用,文本节点一般不用
- 语法:
元素.childNodes
children属性:
- 作用:仅获得所有元素节点,返回的还是一个伪数组,且是所有亲儿子元素
- 语法:
元素.children
示例:
<body>
<ul>
<li>
<p>亲儿子元素的内容</p>
</li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
<script>
const ul = document.querySelector('ul')
console.dir(ul.children) // 伪数组
</script>
</body>
点开第一个li,发现亲儿子元素的内容也获取到了,但不是孙子元素本身!
2.3 兄弟节点查找
- 下一个兄弟节点:
nextElementSibling
属性 - 上一个兄弟节点:
previousElementSibling
属性
示例:
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
<script>
const li2 = document.querySelector('ul li:nth-child(2)')
// 获取li1
console.log(li2.previousElementSibling)
// 获取li4
console.log(li2.nextElementSibling.nextElementSibling)
</script>
</body>
3、新增节点
实现步骤:
- 创建一个新的节点
- 把创建的新的节点放入到指定的元素内部
3.1 创建新节点
// 创建一个新的元素节点
document.createElement('标签名')
eg:
<script>
const div = document.createElement('div')
</script>
3.2 追加节点
要想在界面看到,还得把创建的新节点插入到某个父元素中:
- 插入到父元素的最后一个子元素:
// 示例:
<script>
const div = document.createElement('div')
document.body.appendChild(div)
</script>
- 插入到父元素中某个子元素的前面:
<body>
<ul></ul>
<script>
const ul = document.querySelector('ul')
const li = document.createElement('li')
li.innerHTML = '我是创建的'
// 插入到第一个孩子的前面
ul.insertBefore(li, ul.children[0])
</script>
</body>
3.3 克隆节点
除了新创建节点,也可以复制一个原有的节点,然后再把复制的节点放入到指定的元素内部
cloneNode会克隆返回出一个跟原标签一样的元素,传参为布尔,决定了深拷贝还是浅拷贝,默认false,浅拷贝:
- 传true,克隆时会包含后代节点一起克隆
- 传false,克隆时不包含后代节点
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
const ul = document.querySelector('ul')
// 克隆li1
const li = ul.children[0].cloneNode(true)
// 追加
ul.appendChild(li)
</script>
</body>
上面传参是true,如果不传,也就是false,那就只克隆一个li标签,第一个li标签的内容 “1”是不会克隆的:
3.4 案例:学成在线页面数据渲染
实现思路:
- 准备一个空的ul标签
- 遍历数据,创建一个新的空的li,li里面再修改内容、标题、img等,这里的修改直接innerHTML = `` 就行,复制一个html的死的数据格式,放反引号里用模板字符串
- 追加给ul标签
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>学车在线首页</title>
<link rel="stylesheet" href="./css/style.css">
<style>
</style>
</head>
<body>
<!-- 4. box核心内容区域开始 -->
<div class="box w">
<div class="box-hd">
<h3>精品推荐</h3>
<a href="#">查看全部</a>
</div>
<div class="box-bd">
<!-- 准备了一个空ul -->
<ul class="clearfix">
</ul>
</div>
</div>
<script>
// 1. 源数据
let data = [
{
src: 'images/course01.png',
title: 'Think PHP 5.0 博客系统实战项目演练',
num: 1125
},
{
src: 'images/course02.png',
title: 'Android 网络动态图片加载实战',
num: 357
},
{
src: 'images/course03.png',
title: 'Angular2 大前端商城实战项目演练',
num: 22250
},
{
src: 'images/course04.png',
title: 'Android APP 实战项目演练',
num: 389
},
{
src: 'images/course05.png',
title: 'UGUI 源码深度分析案例',
num: 124
},
{
src: 'images/course06.png',
title: 'Kami2首页界面切换效果实战演练',
num: 432
},
{
src: 'images/course07.png',
title: 'UNITY 从入门到精通实战案例',
num: 888
},
{
src: 'images/course08.png',
title: 'Cocos 深度学习你不会错过的实战',
num: 590
},
]
const ul = document.querySelector('.box-bd ul')
// 1. 根据数据的个数,创建 对应的小li
for (let i = 0; i < data.length; i++) {
// 2. 创建新的小li
const li = document.createElement('li')
// 把内容给li
li.innerHTML = `
<a href="#">
<img src=${data[i].src} alt="">
<h4>
${data[i].title}
</h4>
<div class="info">
<span>高级</span> • <span>${data[i].num}</span>人在学习
</div>
</a>
`
// 3. ul追加小li
ul.appendChild(li)
}
</script>
</body>
</html>
效果:
4、删除节点
在JavaScript 原生DOM操作中,要删除元素必须通过父元素删除(如果不存在父子关系则删除不成功),语法:
要删除的元素的父元素.removeChild(要删除的元素)
删除节点和隐藏节点(display:none) 的区别:隐藏节点还是存在的,但是删除,则从html中删除节点
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
const ul = document.querySelector('ul')
// ul.children[0],现在有了元素关系,需要一个元素时,别总想着去querySelector,动关系去找
ul.removeChild(ul.children[0])
</script>
</body>
效果: