从ECMA到W3C
我们知道,ECMA定义的是js的变量语法等基础的标准规范,而W3C是针对浏览器API提出的规范, 所以我们要工作不可能只了解语法,我们的代码要在浏览器上跑起来就需要我们去了解W3C的标准。
那么W3C规定了哪一系列的的API呢,DOM、BOM、AJAX、事件、存储等等。window.document,这个就是W3C提出的浏览器内置更多的对象之一。
API的概念
API(Application Programming Interface,应用程序编程接口)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组程序的能力,而又无需访问源码,无需理解其内部工作机制细节,只需直接调用使用即可。
总之API就是为我们程序员提供了一个接口,帮助我们实现某种功能。
Web API的概念
Web API 是浏览器提供的一套操作浏览器功能和页面元素的 API ( BOM 和 DOM )。
什么是DOM?
HTML DOM 是W3C (万维网联盟)制订的一套标准,标准中定义了所有 HTML 元素的对象和属性,以及访问它们的方法。换言之,HTML DOM 是关于如何获取、修改、添加或删除 HTML 元素的标准。
注意:DOM 是 Document Object Model(文档对象模型)的缩写。
DOM 节点
根据 W3C 的 HTML DOM 标准,HTML 文档中的所有内容都是节点:
-
整个文档是一个文档节点
-
每个 HTML 元素是元素节点
-
HTML 元素内的文本是文本节点
-
每个 HTML 属性是属性节点
-
注释是注释节点
DOM 节点树
DOM树 又称为文档树模型,把文档映射成树形结构,通过节点对象对其处理,处理的结果可以加入到当前的页面。
-
文档:一个页面就是一个文档,DOM中使用document表示
-
节点:网页中的所有内容,在文档树中都是节点(标签、属性、文本、注释等),使用node表示
-
标签节点:网页中的所有标签,通常称为元素节点,又简称为“元素”,使用element表示
-
DOM把以上内容都看做对象。(对象可以有属性和方法)
-
通过 HTML DOM,树中的所有节点均可通过 JavaScript 进行访问。所有 HTML元素(节点)均可被修改,也可以创建或删除节点。
获取元素节点
为什么要获取页面元素?
例如:我们想要操作页面上的某部分(显示/隐藏,动画),需要先获取到该部分对应的元素,再对其进行操作。
假设页面中包含如下代码,我们怎样使用 DOM 提供的方法获取这些节点呢?
<!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 class="box" id="pox">昨天晚上下大雨了?</div>
<div class="box">昨天晚上下大雨了?2</div>
<div class="box">昨天晚上下大雨了?3</div>
<div class="box">昨天晚上下大雨了?4</div>
<div>昨天晚上下大雨了?5</div>
<script>
// 1.通过标签名获取节点
// 获取到所有对应标签的元素组成的伪数组
// 获取到确定的某个元素,跟上该元素对应的索引下标
var box = document.getElementsByTagName("div")[4];
console.log(box);
// 2.通过类名获取节点
// 获取到所有对应类名的元素组成的伪数组
// 获取到确定的某个元素,跟上该元素对应的索引下标
var box1 = document.getElementsByClassName("box")[1];
console.log(box1);
// 3.通过id获取节点,直接获取到确定的元素
var pox = document.getElementById("pox");
console.log(pox);
</script>
</body>
</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>
</head>
<body>
<script>
// 获取整个 html 节点
var ohtml = document.documentElement;
console.log(ohtml);
// 获取 body
var obody = document.body;
console.log(obody);
// 获取页面标题
var tit = document.title;
console.log(tit);
</script>
</body>
</html>
改变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>
</head>
<body>
<div>今天中午吃啥饭?</div>
<script>
// 1.获取节点
var box = document.getElementsByTagName("div")[0];
console.log(box);
// 修改节点HTML内容
// 1.innerText
box.innerText = "修改后的内容";
// 2.innerHTML
box.innerHTML = "修改后的内容2";
// 3.innerText 和 innerHTML 的区别: innerText只能插入文本,不能识别标签;innerHTML可以识别标签。
box.innerText = "<b>加粗的内容</b>";
box.innerHTML = "<b>加粗的内容</b>";
// 获取节点内容
var text = box.innerText;
console.log(text);
</script>
</body>
</html>
改变css样式
<!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{
width: 200px;
height: 200px;
color: red;
background-color: aquamarine;
}
</style>
</head>
<body>
<div class="box">今天中午吃啥饭?</div>
<script>
// 1.获取元素
var box = document.getElementsByClassName("box")[0];
// 改变元素 CSS 样式, 一个单词直接写;如果单词中间出现连词符 "-", 去掉连词符,后面的单词首字母大写
// 通过 .style.样式 修改或添加的样式会出现在行内
box.style.color = "#00f";
box.style.backgroundColor = "#f00";
box.style.fontSize = "30px";
</script>
</body>
</html>
改变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>
</head>
<body>
<div class="box">天生我材必有用,千金散尽还复来。</div>
<script>
// 获取元素
var box = document.getElementsByClassName("box")[0];
console.log(box);
// 1. 元素.属性名
console.log(box.className);
// 修改元素属性
// box.className = "pox";
// 2. 通过 getAttribute() 获取属性
console.log(box.getAttribute("class"));
// 通过 setAttribute() 设置属性
box.setAttribute("class","pox pox2");
// 删除属性 removeAttribute()
// box.removeAttribute("class");
</script>
</body>
</html>
操作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>
</head>
<body>
<script>
// 新建文本节点
var textNode = document.createTextNode("你好");
console.log(textNode);
// 新建节点
var newEle = document.createElement("p");
newEle.appendChild(textNode);
console.log(newEle);
</script>
</body>
</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>
</head>
<body>
<div>123</div>
<script>
// 新建文本节点
var text = document.createTextNode("456");
// 获取父节点
var box = document.getElementsByTagName("div")[0];
// 将新建文本节点追加到父节点里面
box.appendChild(text);
</script>
</body>
</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>
</head>
<body>
<div>
<i>天生我材必有用,千金散尽还复来。</i>
</div>
<script>
// 获取节点
// 父节点
var box = document.getElementsByTagName("div")[0];
// 目标节点
var ibox = document.getElementsByTagName("i")[0];
// 新建节点
var bold = document.createElement("b");
// 插入节点 父节点.insertBefore(新建节点,目标节点);
box.insertBefore(bold,ibox);
// 注意:没有 insertAfter()
// 要想在父节点后面插入 appendChild()
</script>
</body>
</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>
</head>
<body>
<div>
<i>天生我材必有用,千金散尽还复来。</i>
</div>
<script>
// 获取节点
// 父节点
var box = document.getElementsByTagName("div")[0];
// 目标节点
var ibox = document.getElementsByTagName("i")[0];
// 新建节点
var bold = document.createElement("b");
// 替换节点 父节点.replaceChild(新节点,目标节点);
box.replaceChild(bold,ibox);
</script>
</body>
</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>
</head>
<body>
<div>
<i>天生我材必有用,千金散尽还复来。</i>
</div>
<script>
// 获取节点
// 父节点
var box = document.getElementsByTagName("div")[0];
// 目标节点
var ibox = document.getElementsByTagName("i")[0];
// 删除节点
box.removeChild(ibox);
// 获取元素
var box = document.getElementsByTagName("div")[0];
// 删除本身节点
box.remove();
</script>
</body>
</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>
</head>
<body>
<div>
<i>天生我材必有用,千金散尽还复来。</i>
</div>
<script>
// 获取元素
var box = document.getElementsByTagName("div")[0];
console.log(box);
// 克隆节点 默认情况只克隆节点本身,而不克隆节点内的元素;
var cloneBox = box.cloneNode();
console.log(cloneBox);
// 深度克隆
var cloneBox2 = box.cloneNode(true);
console.log(cloneBox2);
</script>
</body>
</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>
</head>
<body>
<div class="father">
<div class="pox1">000</div>
<div class="box">
<div class="box1">123</div>
<div class="box2">456</div>
</div>
<div class="pox">
789
</div>
</div>
<script>
// 获取父节点
var box = document.getElementsByClassName("box")[0];
// 1.下一个兄弟节点
// nextSibling 幽灵节点(看不见摸不着,只是放在那里)
console.log(box.nextSibling); // #text
// nextElementSibling 下一个兄弟节点 IE9以上才支持
console.log(box.nextElementSibling);
// 2.上一个兄弟节点
// previouosSibling 幽灵节点
console.log(box.previousSibling); // #text
// previousElementSibling 上一个兄弟节点 IE9以上才支持
console.log(box.previousElementSibling);
// 3.访问第一个孩子节点
// firstChild 幽灵节点
console.log(box.firstChild); // #text
// firstElementChild 第一个孩子节点 IE9以上才支持
console.log(box.firstElementChild);
// 4.访问最后一个孩子节点
// lastChild 幽灵节点
console.log(box.lastChild);
// lastElementChild 最后一个孩子节点
console.log(box.lastElementChild);
// 5.访问孩子节点
// childNodes 所有孩子节点组成的伪数组,包括幽灵节点
console.log(box.childNodes);
// children 所有孩子节点组成的伪数组,不包括幽灵节点
console.log(box.children[1]);
</script>
</body>
</html>
旗帜法则(实用小技巧)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.bg {
cursor: pointer;
width: 400px;
height: 600px;
}
</style>
</head>
<body>
<img src="img/图片1.webp" alt="" class="bg">
<script>
var bg = document.getElementsByClassName("bg")[0];
// 默认 flag 为1,代表此时页面上的第一个图片
var flag = 1;
// 给图片添加单击事件
bg.onclick = function() {
// if判断 如果flag是默认图片的话就会进入第一个判断
if (flag == 1) {
// 将img的属性值src更换成第二张图片
bg.src = "img/图片2.webp";
// flag等于2是为了让他继续判断
flag = 2;
// 此时 就是如果flag为2的话就会进入这个判断 以此类推
} else if (flag == 2) {
bg.src = "img/图片3.webp";
flag = 3;
} else if (flag == 3) {
// 最后结束的时候一定要将图片返回为默认的哦
bg.src = "img/图片1.webp";
flag = 1;
}
}
</script>
</body>
</html>