1.WebAPI背景知识
1.1什么是WebAPI
前面学习的JS分成三大部分:
- ECMAScript: 基础语法部分
- DOM API: 操作页面结构
- BOM API: 操作浏览器
WebAPI 就包含了 DOM BOM.本博客中我们主要学习DOM API.
1.2什么是API
API 是一个更广义的概念. 而 WebAPI 是一个更具体的概念, 特指 DOM BOM
所谓的 API 本质上就是一些现成的函数/对象
, 让程序猿拿来就用, 方便开发.
具体可查看:
API参考文档
2.DOM基本概念
2.1什么是DOM
DOM
全称为 Document Object Model
, 是页面文档对象模型, html中的每个标签都是可以映射到JS中的一个对象中的, 标签中的内容都可以通过JS对象感知到, JS对象修改对应的属性能够影响到标签的展示, 通过这样的DOM API就可以让JS代码来操作页面元素.
2.2常用的DOMAPI
2.2.1.选中页面元素
在DOM中, 任何一个页面, 都会有一个document
对象, 是页面的一个全局对象, 所有的DOM API都是通过document对象类展开的, 其中document对象中的querySelector
和querySelectorAll
函数可以用来选择元素, 通过传入CSS选择器来达到目的, 选择的范围是位于该函数之前所存在的选择器, 没找到返回值为null
.
let obj = document.querySelector('选择器');
querySelector
函数如果符合选择的标签在页面中有多个, 就只会选择
在页面中第一次出现的标签
.
如果想把符合选择的元素都选中就需要使用querySelectorAll
函数了, 在使用上和和querySelector 是一样的.
let elem = document.querySelectorAll('选择器');
使用该函数会返回一个类似于数组的对象, 用法和数组相同.
将得到的数组对象里面的元素展开查看, 会发现有很多的属性, 这些属性都是DOM原生的一些属性.
2.2.2操作元素的属性
1. 事件概念
JS要构建动态页面, 就需要感知到用户的行为, 而 “事件” 就是针对用户的操作进行的一些响应, 比如鼠标点击, 鼠标移动, 键盘输入, 调整浏览器窗口这些都是用户的操作, 而代码就需要根据这些事件做出相应的响应.
事件的三要素:
- 事件源, 哪个HTML元素产生的事件.
- 事件类型, 比如鼠标点击, 鼠标移动, 键盘输入等.
- 事件处理程序, 当事件发生之后,要执行哪个代码.
前端页面中, 针对不同的事件也是有不同的处理方式的, 而处理方式都是最开始的时候就设定好的(事件绑定).
最简单的方式,直接在元素中使用onXXX
这样的方式,来绑定一个事件处理程序.
<button onclick ="alert('hello')">点我!</button>
如果事件处理的代码比较多的话使用上面这种写法就不太合适了, 所以更推荐的是下面这种写法, 可以直接使用onXXX
这样的方法进行绑定, 效果和上面是一样的.
<script !src="">
let button = document.querySelector("button");
button.onclick = function(){
alert("hello");
}
</script>
<button onclick ="alert('hello')">点我!</button>
2.获取/修改元素内容
在选中元素后, 就可以使用innerHTML属性来获取/修改一个标签里面的内容了.
代码语言:javascript复制//1.选中标签
let var_name = document.querySelector();
//2.获取内容
let content = var_name.innnerHTML;
//3.修改内容
var_name.innerHTML = '修改值';
观察控制台的结果, 控制台中多次点击按钮的结果都被折叠输出了, 这是因为chrome控制台会默认把相邻且相同的日志进行合并, 另外再显示一个数字表示输出的次数, 我们可以点击开发者工具的设置栏, 设置一下让它不合并就行了.
还要注意的是, 通过innerHTML
是可以获取到div内部的html结构
的, 比如下面的的代码, 会将div标签中的html代码也获取到, 而innerText
只能获取文本内容
, 并不能获取html结构, innerHTML用的场景是要比innerText更多的.
修改元素如下所示:
计数器 有了上面的获取和修改元素的知识, 我们这里实现一个简单的计数器, 就是点击一下按钮, 计数器就 1.
实现思路也很简单, 用户的点击操作, 就会触发点击事件, 就是先获取到计数元素中的内容, 然后将元素内容进行加一操作再写回元素中, 代码如下:
这个代码要注意的是, num.innerHTML
这里拿到的元素内容是字符串类型的, 直接进行加法运算就是字符串拼接的效果了, 而要完成算数相加的效果就需要将字符串转换为整数, 和Java中类似, 可以使用parseInt
方法将字符串转换为整数, 而如果是浮点数就使用parseFloat方法
点击十次就爆炸~
<div id="count">10</div>
<button id="counter">点击十次就爆炸</button>
<script !src="">
let counter = document.querySelector('#counter');
counter.onclick = function(){
let num = document.querySelector('#count');
num1 = parseInt(num.innerHTML)-1;
num.innerHTML = num1;
if(num.innerHTML == 0){
num.innerHTML = 'Boom!';
}
};
3. 获取/修改元素属性
点击图片切换
上面介绍的是修改元素(标签)中的内容, 我们还可以在代码中使用DOM直接获取元素的属性并修改元素的属性, 比如这里实现一个效果, 就是点击一个图片就可以切换到另一张图片, 然后再点击就能再切换回来, 这个案例我们只需要设置点击事件为修改图片的路径即可, 也就是修改src
属性.
点击前:
点击后:
一个标签中具体有哪些属性可以修改, 可以使用console.dir()
函数来获取DOM API能够操作的全部属性, 比如img
元素.
4.获取/修改表单元素属性
这里把表单元素单拎出来是因为, 表单元素中有一些特别的属性是普通标签没有的, 主要需要区别的是一些表单元素想要获取其中用户输入的内容的话是不能通过innerHTML拿到的, 这是因为input, textarea… 这些标签元素都是单标签, 是没有内容的, 正确的获取/修改的方式应该是通过这些标签的value
属性来进行.
表单计数器
<input type="text" value="0" id='count'>
<button id='countAdd'>计数器: 点击 1</button>
<script !src="">
let counterAdd = document.querySelector('#countAdd');
counterAdd.onclick = function () {
let num = document.querySelector('#count');
numAdd = parseInt(num.value) 1
num.value = numAdd;
};
</script>
再举例一个比较常见的场景, 我们平常见的登录功能中密码框中的文本可以选择是否显示密码, 这个实现起来其实也很简单, 通过DOM来修改type
属性的值即可.
<input type="text" id="pw">
<button>隐藏密码</button>
<script !src="">
let pw = document.querySelector('#pw');
let button = document.querySelector('button');
button.onclick = function() {
if (pw.type == 'text') {
pw.type = 'password';
button.innerHTML = '显示密码';
} else {
pw.type = 'text';
button.innerHTML = '隐藏密码';
}
}
</script>
5.获取修改样式属性
第一种方式是通过修改元素的内联样式, 即修改元素的style属性的值来指定样式, 这种方式的优先级很高, 适用于该样式比较少的情况.
代码语言:javascript复制 <div style="font-size: 10px;">
这是一段文本,点击字体变大
</div>
<script !src="">
let div = document.querySelector('div');
div.onclick = function(){
//获取文字大小属性
let size = parseInt(div.style.fontSize);
console.log("修改前:" size);
//修改文字大小
size = 5;
//写回到属性
div.style.fontSize = size "px";
console.log("修改后:" size);
}
</script>
还有一种修改样式的方式可以通过修改类属性来达到修改样式的效果, 可以通过元素.className
来获取/修改类属性的值, 由于class
是 JS 的保留字, 所以这里获取类属性的名字叫做className.
实现夜间/日间模式的切换
<div class="container light">
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Sed, praesentium architecto harum doloremque eum nesciunt! Nemo alias quaerat quas, temporibus sit commodi aut architecto maiores autem vero praesentium deserunt deleniti. </p><br>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Sed, praesentium architecto harum doloremque eum nesciunt! Nemo alias quaerat quas, temporibus sit commodi aut architecto maiores autem vero praesentium deserunt deleniti. </p><br>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Sed, praesentium architecto harum doloremque eum nesciunt! Nemo alias quaerat quas, temporibus sit commodi aut architecto maiores autem vero praesentium deserunt deleniti. </p><br>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Sed, praesentium architecto harum doloremque eum nesciunt! Nemo alias quaerat quas, temporibus sit commodi aut architecto maiores autem vero praesentium deserunt deleniti. </p><br>
</div>
<style>
*{
margin: 0;
padding: 0;
}
html,body{
width:100%;
height: 100%
}
.container{
width: 100%;
height: 100%;
}
.light{
background-color:rgb(235, 235, 237);
color: black;
}
.dark{
background-color: gray;
color: white;
}
</style>
<script !src="">
let div = document.querySelector('div');
div.onclick = function(){
console.log(div.className);
if(div.className.indexOf('light') != -1){
div.className = 'container dark';
}else{
div.className = 'container light';
}
}
</script>
2.2.3.操作页面节点
上述涉及的操作都是针对页面已有的元素进行操作的, 利用DOM API还可以完成添加/删除元素的操作.
1.新增节点
添加元素主要有两个步骤, 首先需要创建一个新的创建元素节点, 然后把这个元素节点插入到父元素中就能完成元素的的添加(依赖于DOM树).
可以使用creatElement
方法来创建一个新的元素:
let element = document.createElement('元素标签名');
插入到DOM树中:
代码语言:javascript复制父元素.appendChild(创建的子元素);
关于插入节点还可以使用insertBefore将节点插入到指定节点之前.
代码语言:javascript复制新插入节点的父元素.insertBefore(新插入的元素, 指定节点(将要插在这个节点之前));
代码语言:javascript复制<div class="container">
<div>11</div>
<div>22</div>
<div>33</div>
<div>44</div>
</div>
<script>
var newDiv = document.createElement('div');
newDiv.innerHTML = '新节点';
var container = document.querySelector('.container');
console.log(container.children);
container.insertBefore(newDiv,container.children[0]);
</script>
2.删除节点
代码语言:javascript复制父元素.removeChild(需要删除的子元素);
3.案例
猜数字游戏
代码语言:javascript复制<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Game</title>
</head>
<body>
<button id="flash">重新开始</button>
<div>请输入1-100之内要猜的数字</div>
<input type="text">
<button id="submit">提交</button>
<!-- 用这个div来显示猜测结果 -->
<div class="result"></div>
<script>
//1.生成一个1-100之间的随机整数
let toGuess = parseInt(100* Math.random()) 1;
console.log(toGuess);//用于测试,方便查看猜测结果
//2.进行猜数字操作,比较用户输入的数字和生成的随机数大小
let input = document.querySelector('input');//标签选择器
let resultDiv = document.querySelector('.result');//类选择器
let submit = document.querySelector('#submit');//id选择器
submit.onclick = function(){
//取出输入框中的内容
if(input.value == ''){
//输入框没有值,用户未输入,直接返回
return;
}
let inputNum = parseInt(input.value);
//比较大小关系
if(inputNum > toGuess){
resultDiv.innerHTML = '猜大了';
}else if(inputNum < toGuess){
resultDiv.innerHTML = '猜小了';
}else{
resultDiv.innerHTML = '猜对了!'
}
}
//刷新页面
let flash = document.querySelector('#flash');
flash.onclick = function(){
location.reload();
}
</script>
</body>
</html>
留言墙
代码语言:javascript复制<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MessageBoard</title>
<style>
*{
/* 消除浏览器的默认样式 */
margin: 0;
padding: 0;
/* 保证盒子不会撑大 */
box-sizing: border-box;
background-color: rgba(255, 192, 203, 0.436);
}
.container{
width: 600px;
margin: 20px auto;
}
h1 {
text-align: center;
}
p {
text-align: center;
color: #666;
margin: 20px 0;
}
.row {
/* 开启弹性布局 */
display: flex;
height: 40px;
/* 水平方向居中 */
justify-content: center;
/* 垂直方向居中 */
align-items: center;
}
.row span {
width: 80px;
}
.row input {
width: 200px;
height: 30px;
}
.row button {
width: 280px;
height: 30px;
color: white;
background-color: orange;
/* 去掉边框 */
border: none;
border-radius: 5px;
}
/* 点击的时候有个反馈 */
.row button:active {
background-color: grey;
}
</style>
</head>
<body>
<div class="container">
<h1>留言板</h1>
<p>输入内容后点击提交,信息会显示到下方表格中</p>
<div class="row">
<span>谁:</span>
<input type="text">
</div>
<div class="row">
<span>对谁:</span>
<input type="text">
</div>
<div class="row">
<span>说:</span>
<input type="text">
</div>
<div class="row">
<button id="submit">提交</button>
</div>
<div class="row">
<button id="revert">撤销</button>
</div>
</div>
<script>
//实现提交操作,点击提交,就能够吧用户输入的内容提交到页面上显示
//点击时,获取到三个输入框的文本内容
//创建一个新的div.rom把内容构造到这个div中即可.
let containerDiv = document.querySelector('.container');
let inputs = document.querySelectorAll('input');
let button = document.querySelector('#submit');
button.onclick = function(){
//1.获取到三个输入框的内容
let from = inputs[0].value;
let to = inputs[1].value;
let msg = inputs[2].value;
if(from == '' || to == '' || msg == ''){
return;
}
//2.构造新的div
let rowDiv = document.createElement('div');
rowDiv.className = 'row message';
rowDiv.innerHTML = from " 对 " to ' 说 : ' msg;
containerDiv.appendChild(rowDiv);
//3.清空输入聊天框
for(let input of inputs){
input.value = '';
}
let revertButton = document.querySelector('#revert');
revertButton.onclick = function(){
//删除最后一条消息
//选中所有的row,找出最后一个row,然后删除
let rows = document.querySelectorAll('.message');
if (rows == null || rows.length == 0) {
return;
}
containerDiv.removeChild(rows[rows.length - 1]);
}
}
</script>
</body>
</html>