元素的增删改
创建元素
- 使用
document.createElement(标签名)
的方式创建元素
- 使用
- 使用
element.innerHTML=HTML代码片段
的方式创建元素并设置为 element 的后代元素.
element.innerHTML
和element.innerText
的区别: 前者会把文本中的标签文本解析为 HTML 标签元素; 后者则把标签文本当作文本直接输出.
- 使用
插入元素
- 使用
element.appendChild(新元素)
的方式向父元素中插入新元素. 新元素将被插入到兄弟元素中最后的位置.
- 使用
- 使用
element.insertBefor(新元素, 兄弟元素)
的方式在父元素中的某个子元素前插入新元素. 新元素将被插入在指定的兄弟元素之前.
- 使用
删除元素
删除元素需要调用父元素的
removeChild(待删除子元素)
方法来执行删除.- 获取当前元素的父元素, 使用
element.parentNode
属性.
- 获取当前元素的父元素, 使用
补: 获取子节点和获取子元素的相关方法对比
- 获取所有子节点, 用
element.childNodes
属性; - 获取所有子元素, 用
element.children
属性; - 获取子节点数量, 用
element.childNodes.length
属性; - 获取子元素数量, 用
element.childElementCount
属性, 或者element.children.length
属性; - 获取第一个子节点, 用
element.firstChild
属性, 或者element.childNodes[0]
, 或者element.childNodes.item(0)
; - 获取第一个子元素, 用
element.firstElementChild
属性, 或者element.children[0]
, 或者element.children.item(0)
; - 获取最后一个子节点, 用
element.lastChild
属性, 或者element.children[element.childNodes.length -1]
, 或者element.children.item(element.childNodes.length -1)
; - 获取最后一个子元素, 用
element.lastElementChild
, 或者element.children[element.childElementCount - 1]
, 或者element.children.item(element.childElementCount - 1)
; - 获取当前节点的前一个兄弟节点, 用
nodeElement.previousSibling
属性; - 获取当前元素的前一个兄弟元素, 用
eleElement.previousElementSibling
属性; - 获取当前节点的后一个兄弟节点, 用
nodeElement.nextSibling
属性; - 获取当前元素的后一个兄弟元素, 用
eleElement.nextElementSibling
属性;
- 获取所有子节点, 用
选项卡实战
实现原理
- 使用自定义属性关联选项卡标签和内容区, 即有关联的标签和内容区的
data-index
相同. - 非活动的标签和内容区隐藏.
- 当动作事件(如: 点击事件/鼠标移入事件等)触发时, 执行切换选项卡高亮和内容区显示/隐藏操作.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>选项卡</title>
<style>
@import 'tabs.css';
</style>
</head>
<body>
<!-- 选项卡的页签部分 -->
<div class="tabs">
<ul class="tab">
<!-- 默认显示水果页签内容 -->
<li class="active" data-index="1">水果</li>
<li data-index="2">手机</li>
<li data-index="3">汽车</li>
</ul>
<!-- 页签内容 -->
<!-- 1. 水果页签内容 -->
<ul class="active" data-index="1">
<li>苹果</li>
<li>雪梨</li>
<li>香蕉</li>
<li>橙子</li>
</ul>
<!-- 2. 手机页签内容 -->
<ul data-index="2">
<li>华为</li>
<li>荣耀</li>
<li>OPPO</li>
<li>VIVO</li>
</ul>
<!-- 3. 汽车页签内容 -->
<ul data-index="3">
<li>大众</li>
<li>丰田</li>
<li>本田</li>
<li>别克</li>
</ul>
</div>
</body>
<script>
// 导航区
var tab = document.querySelector('.tab');
// 导航快
var tabItems = document.querySelector('.tab li');
// 把导航块的点击事件绑定到父元素(.tab), 利用冒泡机制触发
tab.addEventListener('click', selectItem, false);
// ....鼠标移入.....
// tab.addEventListener('mouseover', selectItem, false);
function selectItem(event) {
// 导航区中非导航块的区域, 鼠标进入时, 不做处理
if (event.target === event.currentTarget) {
return false;
}
// console.log(event.target);
// 获取被点击的导航块的父级元素, 再通过父级元素获取其所有的子节点(注意, 包括文本类型等HTML元素类型之外的子节点)
event.target.parentNode.childNodes.forEach(function(item) {
// 如果当前节点的类型是HTML元素(导航块), 则移除其active样式类
if (item.nodeType === 1) {
item.classList.remove('active');
}
});
// 给当前导航块加上active样式类
event.target.classList.add('active');
// 获取到导航内容区的ul元素
var items = document.querySelectorAll('.tabs ul:not(first-of-type)');
for (var i = 0; i < items.length; i++) {
// 给data-index属性值跟当前被点击的导航块的data-index值相等的导航区增加active样式类
if (items[i].dataset.index == event.target.dataset.index) {
items[i].classList.add('active');
} else {
// 不等的, 则移除active样式类.
items[i].classList.remove('active');
}
}
}
</script>
</html>
效果图:
轮播图实战
实现原理
- 轮播图的图片设置为隐藏, 只显示激活状态的图片.
- 使用自定义属性关联图片和对应的小圆点, 即关联的图片和小圆点具有相同的
data-index
属性值, 点击小圆点, 将关联的图片设置为显示. - 点击上一张/下一张时, 利用
element.previousElementSibling
和element.nextElementSibling
把上一张/下一张图片设置为显示, 并利用data-index
属性把关联的小圆点设置为高亮. - 利用定时器, 定时执行”下一张”事件自动派发操作.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>轮播图</title>
<style>
@import 'box.css';
</style>
</head>
<body>
<!-- 轮播图 -->
<div class="box">
<!-- 轮播图的图片区域 -->
<img src="img/lb1.png" alt="" class="slider active" data-index="1" />
<img src="img/lb2.png" alt="" class="slider" data-index="2" />
<img src="img/lb3.png" alt="" class="slider" data-index="3" />
<img src="img/lb4.png" alt="" class="slider" data-index="4" />
<!-- 小黑点导航区 -->
<div class="point-list">
<!-- 需要用js动态生成 -->
</div>
<span class="skip prev"><</span>
<span class="skip next">></span>
</div>
</body>
<script>
var cl = console.log.bind(console);
// 获取轮播图片
var imgs = document.querySelectorAll("img");
// 小圆点容器
pointList = document.querySelector(".point-list");
cl(pointList);
// 根据图片的信息动态生成对应的小圆点
imgs.forEach(function(img, index) {
// 生成小圆点
var span = document.createElement("span");
// 增加样式
span.classList.add("point");
span.dataset.index = img.dataset.index;
// 初始状态,第一个小圆点为激活状态
if (index === 0) {
span.classList.add("active");
}
// 添加到小圆点容器中
pointList.appendChild(span);
});
// 为小黑点添加事件(以事件委托的方式,事件添加到小圆点的父节点上)
pointList.addEventListener(
"click",
function(event) {
// 出发点击事件的节点
var currPoint = event.target;
// 执行的事件绑定的节点
var pl = event.currentTarget;
// 点击非小圆点之外的小圆点容器区域, 不做处理
if (pl == currPoint) return false;
// 遍历图片数组
imgs.forEach(function(img, i) {
var imgIndex = img.dataset.index;
// 显示data-index与被点击小圆点的data-index值相同的图片显示, 隐藏当前显示的图片
if (currPoint.dataset.index == imgIndex) {
img.classList.add("active");
currPoint.classList.add("active");
}
// 去掉当前显示的图片以及显示为高亮的小圆点的active样式
else if (img.classList.contains("active")) {
img.classList.remove("active");
var spot = document.querySelector(
'span[data-index="' + imgIndex + '"]'
);
spot.classList.remove("active");
// cl(spot);
}
});
},
false
);
// 获取翻页按钮
var skips = document.querySelectorAll(".skip");
// 绑定点击事件
skips.item(0).addEventListener("click", skipImg, false);
skips.item(1).addEventListener("click", skipImg, false);
function skipImg(event) {
// 判断是上一页还是下一页
var next = this.classList.contains("next") ? "+" : "-";
// 获取当前显示的图片
var img = document.querySelector("img.active");
// 获取显示图片的data-index属性值
var index = img.dataset.index;
// 下一章图片的data-index属性值
var nextIndex = parseInt(eval(index + next + "1"));
cl(typeof nextIndex);
// 边界值处理
nextIndex = nextIndex > 4 ? 1 : nextIndex < 1 ? 4 : nextIndex;
cl(nextIndex);
// 当前显示的图片和对应小圆点取消active样式
img.classList.remove("active");
document.querySelector(".point.active").classList.remove("active");
var nextImg = document.querySelector(
'img[data-index="' + nextIndex + '"]'
);
var nextPoint = document.querySelector(
'.point[data-index="' + nextIndex + '"]'
);
nextImg.classList.add("active");
nextPoint.classList.add("active");
}
// 轮播图容器
var box = document.querySelector(".box");
// 定时器
var timer = null;
// 2. 当鼠标移出轮播图区域时, 加回定时器, 每2秒自动切换图片
box.addEventListener("mouseout", startTimer, false);
// 1. 当鼠标移入轮播图区域时, 清除定时器, 由用户点击操作
box.addEventListener("mouseover", clearTimer, false);
// 利用定时器, 每隔一段时间执行一次事件派发, 自动触发点金"下一页"事件
function startTimer() {
// 创建一个点击事件
var click = new Event("click");
// 创建定时器, 语法: setInterver(间隔执行的回调函数, 间隔的毫秒数);
timer = setInterval(function() {
// 把点击事件派发给"下一页"
skips.item(1).dispatchEvent(click);
}, 2000);
}
startTimer();
// 清楚定时器
function clearTimer() {
// 调用清除定时器的方法
clearInterval(timer);
}
</script>
</html>
运行效果图:
学习心得
- 懒加载理解得不够到位, 选了理解得比较到位的选项卡作为作业.
- 通过本次实战课, 自己对js的各种操作有了进一步的理解. 认识到了他们的使用场景.
- 懒加载主要是各种偏移量, 高度等, 是相对于哪个参照物这点, 理解得不太到位. 在老师给的实例中, 给父元素绑定滚动事件, 而在事件内部, 用
event.target.scrollHeight
来获取子元素的滚动高度, 个人理解,event.target
是父元素,event.target.scrollHeight
应该是父元素的滚动条滚动的高度, 而不是子元素相对于父元素滚动的高度, 这点没绕过来.element.offsetTop
这个值, 是相对于父元素(body)的偏移量, 还是相对于文档内容区(document.documentElement)顶部的偏移量. 这点也比较模糊. 希望老师解惑.