一、前言
作为后端开发,前端其实只需要了解一些就可以了,不需要了解多么深入。在前面我们已经学习了ECMAScript:的基础语法部分,还有DOM API和BOM API需要学习。
DOM API主要负责操作页面结构。
所有的WebAPI可以参考下面这个网址里面的信息
https://developer.mozilla.org/zh-CN/docs/Web/API
那么什么是DOM呢?
DOM全称为Document Object Model.(文件项目模板)所以DOM实际就是W3C 标准给我们提供了一系列的函数, 让我们可以操作:网页内容、网页结构、网页样式。
DOM 树
一个页面的结构是一个树形结构, 称为 DOM 树.
基于DMO的页面结构如下图
DOM的树型结构如下图
- 文档: 一个页面就是一个 文档, 使用 document 表示.
- 元素: 页面中所有的标签都称为 元素. 使用 element 表示.
- 节点: 网页中所有的内容都可以称为 节点(标签节点, 注释节点, 文本节点, 属性节点等). 使用 node 表示.
二、常用的WebAPI介绍
2.1querySelector
这个是 HTML5 新增的, IE9 及以上版本才能使用.
前面的几种方式获取元素的时候都比较麻烦. 而使用 querySelector 能够完全复用前面学过的 CSS 选择 器知识, 达到更快捷更精准的方式获取到元素对象.
var element = document.querySelector(selectors);
- electors 包含一个或多个要匹配的选择器的 DOM字符串 DOMString。 该字符串必须是有效的 CSS选择器字符串(常见的ID选择器#a;类选择器.a;子选择器 a b;标签选择器a);如果不是,则引发 SYNTAX_ERR异常。
- 只返回文档中与指定的一组CSS选择器匹配的第一个元素的 html元素element对象。
- 如果您需要与指定选择器匹配的所有元素的列表,则应该使用querySelectorAll()可以在任何元素上调用,不仅仅是 document。 调用这个方法的元素将作为本次查找的根元素。
示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>js</title>
</head>
<body>
<div class="box">
abc
</div>
<div id="id">
def
</div>
<h3>
<span>
<input type="text">
</span>
</h3>
<script>
let elem1 = document.querySelector('.box');
console.log(elem1);
let elem2 = document.querySelector('#id');
console.log(elem2);
let elem3 = document.querySelector('h3 span input');
console.log(elem3);
let elems = document.querySelectorAll('div');
console.log(elems);
</script>
</body>
</html>
注意:
- document.querySelector()实参一定要是也给字符串类型,必须用’'括起来再输入,否则报错。
- document.querySelectorAll()返回的实际是一个类型为div的数组。
- elem1、elem2、elem3、elems、不是胡乱命名的,而是一定要这样命名,否则会报错
let elemms = document.querySelectorAll('div');//变量命名为elemms就会报错。
console.log(elems);
三、事件
3.1事件是什么
要能够和用户交互,就需要知道用户在浏览器中做了什么,也就称之为事件,代码就是需要做的就是针对这些事件给出响应。
常见的事件比如:鼠标单击、鼠标双击、鼠标移动、键盘按下、调整浏览器窗口等。
3.2事件三要素
- 事件源: 哪个元素触发的
- 事件类型: 是点击, 选中, 还是修改?
- 事件处理程序: 进一步如何处理. 往往是一个回调函数.
3.3事件绑定
在前端设计的时候我们就需要根据各种事件进行针对性的处理,对每一个事件的发生进行预估并写好相应的处理代码,这就是事件绑定。
举个例子
<div class="box" onclick="alert(hello)">
abc
</div>
这就是一个最简单的事件绑定,在点击abc之后弹出hello的弹窗。
在元素中使用onxxxx来表示一旦触发某个事件就执行啥。但是这种方式在实际开发中并不推荐,这实际就将html和js混在一起用了,不行!!!
所以我就需要使用 document.querySelector()
将这个元素取出
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>js</title>
</head>
<body>
<div class="box">
abc
</div>
<script>
let elem1 = document.querySelector('.box');
elem1.onclick = function(){
alert('hello')
}
</script>
</body>
</html>
- elem1 就是事件源.
- 点击(onclick)就是事件类型
- function 这个匿名函数就是事件处理程序
- elem1.onclick = function() 这个操作称为 注册事件/绑定事件
- 这个匿名函数相当于一个回调函数, 这个函数不需要程序猿主动来调用, 而是交给浏览器, 由浏览器 自动在合适的时机(触发点击操作时) 进行调用.
四、操作元素
4.1获取属性 innerHTML
Element.innerHTML
属性设置或获取HTML语法表示的元素的后代.
1. 读取页面内容
<script>
let elem1 = document.querySelector('.box');//读取页面内容
console.log(elem1.innerHTML);
</script>
2. 写入或者修改页面内容
<body>
<div class="box">
abc
</div>
<script>
let elem1 = document.querySelector('.box');
console.log(elem1.innerHTML);
elem1.innerHTML = 'abcd';
</script>
</body>
<body>
<div class="box">
abc
</div>
<script>
let elem1 = document.querySelector('.box');
console.log(elem1.innerHTML);
elem1.innerHTML = '<p>只因你太美<p>';
console.log(elem1.innerHTML);
</script>
</body>
可以看到 innerHTML 不光能获取到页面的 html 结构, 同时也能修改结构. 并且获取到的内容保留的空格和换行.
4.2获取/修改元素属性
可以通过 Element 对象的属性来直接修改, 就能影响到页面显示效果。
HTML中标签的属性也会在JS中映射一个对象来表示这个属性。
比如说来一个案例点击一个图片这个图片就会更改为另一个图片
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>js</title>
</head>
<body>
<img src="坤坤.png" alt="哎呀图片不见了!" >
<script>
let img1 = document.querySelector('img');
console.log(img1.src);
console.log(img1.title);
img1.onclick = function(){
img1.src = "鸡你太美.jpg";
img1.title = "鸡你太美";
console.log(img1.src);
console.log(img1.title);
}
</script>
</body>
</html>
点击之后
此外我们可以通过.dir来获取一个元素(对象)的所有属性。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>js</title>
</head>
<body>
<img src="坤坤.png" alt="哎呀图片不见了!" >
<script>
let img1 = document.querySelector('img');
console.dir(img1);
</script>
</body>
</html>
4.3获取/修改表单元素属性
表单(主要是指 input 标签)的以下属性都可以通过 DOM 来修改
- value: input 的值.
- disabled: 禁用
- checked: 复选框会使用
- selected: 下拉框会使用
- type: input 的类型(文本, 密码, 按钮, 文件等)
我们这里用input来举例
我们来一个案例
设置一个输入框,一个按钮,输入一个文本后,点击按钮就可以获取一次输入的文本,并打印。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>js</title>
</head>
<body>
<input type="text">
<button>点我一下</button>
<script>
let input = document.querySelector('input');
let button = document.querySelector('button');
button.onclick = function(){
console.log(input.value);
}
</script>
</body>
</html>
- 获取input标签里面的输入内容使用的是
input.value
;而不是使用innerHTML
,因为input里面是单标签,innerHTML`获取的实际就可以理解为是两个<>中间的东西,以字符串形式返回,但是单标签根本没有这个东西。
再来几个应用场景
设置一个播放按钮, 在 “播放” - “暂停” 之间切换.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>js</title>
</head>
<body>
<button>播放</button>
<script>
let button = document.querySelector('button');
button.onclick = function(){
if(button.innerHTML == '播放'){
button.innerHTML = '暂停';
}else{
button.innerHTML = '播放';
}
}
</script>
</body>
</html>
点击计数
使用一个输入框输入初始值(整数). 每次点击按钮, 值 + 1
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>js</title>
</head>
<body>
<button>1</button>
<script>
let button = document.querySelector('button');
button.onclick = function(){
button.innerHTML += 1;
}
</script>
</body>
</html>
这样写是不对的,达不到预期效果
每次点击会以字符串的形式在后面加上一个字符1。
所以应该像下面这样
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>js</title>
</head>
<body>
<input type="text" id="text" value="0">
<input type="button" id="btn" value='点我+1'>
<script>
var text = document.querySelector('#text');
var btn = document.querySelector('#btn');
btn.onclick = function () {
var num = +text.value;
console.log(num);
num++;
text.value = num;
}
</script>
</body>
</html>
- input 具有一个重要的属性 value, 这个 value 决定了表单元素的内容。
- 如果是输入框, value 表示输入框的内容, 修改这个值会影响到界面显式; 在界面上修改这个值也会 影响到代码中的属性。
- 如果是按钮, value 表示按钮的内容. 可以通过这个来实现按钮中文本的替换。
制作一个按钮可以隐藏和显示密码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>js</title>
</head>
<body>
<input type="text">
<button>隐藏密码</button>
<script>
let input = document.querySelector('input');
let button = document.querySelector('button');
button.onclick = function(){
if(input.type == 'text'){
input.type = 'password';
button.innerHTML = '显示密码';
}
else{
input.type = 'text';
button.innerHTML = '隐藏密码';
}
}
</script>
</body>
</html>
4.4获取/修改样式属性
1. 行内样式操作
element.style.[属性名] = [属性值];
element.style.cssText = [属性名+属性值];
我们先来一个案例
点击文字则放大字体.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>js</title>
</head>
<body>
<div style="font-size: 20px;">鸡你太美</div>//style作为属性值,这是HTML的语法,css是将style作为标签。
<script>
let div = document.querySelector('div');
div.onclick = function(){
let num = parseInt(div.style.fontSize);
num = num+10;
div.style.fontSize = num + "px"//最后不要忘记加单位px.
}
</script>
</body>
</html>
这里面有几个点需要说明
- style 中的属性都是使用 驼峰命名 的方式和 CSS 属性对应的.例如: font-size => fontSize, background-color => backgroundColor 等 这种方式修改只影响到特定样式, 其他内联样式的值不变.
- parseInt函数的作用在于div.style.fontSize的返回值是一个字符串,然后parseInt函数是遍历这个字符串,遇到数字字符就转化为对于的整型数字,直到遇到第一个非数字型字符就停止,所以这里实际返回了当前字符大小的整型数值。
2.类名样式操作
element.className = [CSS 类名];
代码示例: 夜间模式和日间模式切换
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>js</title>
<style>
.light{
background-color: white;
color: black;
}
.night{
background-color: black;
color: white;
}
</style>
</head>
<body>
<div class="light" style="height: 500px;">这是一段话</div>
<script>
let div = document.querySelector('div');
div.onclick = function(){
if(div.className == 'light'){
div.className = 'night';
}else{
div.className = 'light';
}
}
</script>
</body>
</html>
div.className == 'light'
之所以不用div,class == ‘night’;由于 class 是 JS 的保留字, 所以名字叫做 className
五、新增元素
5.1创建元素节点
上述操作都是针对当前页面上以后元素进行的操作,那么JS中如何创建元素呢?
在DOM中每一个元素都是都是一个节点
使用 createElement 方法来创建一个元素. options 参数暂不关注.
var element = document.createElement(tagName[, options]);
示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>js</title>
</head>
<body>
<script>
let div = document.createElement('div');
div.innerHTML = '这是一段文字';
div.style = 'font-size: 40px';
div.id = 'mydiv';
</script>
</body>
</html>
- 上面介绍的只是创建元素节点, 还可以使用:createTextNode 创建文本节点、createComment 创建注释节点、createAttribute 创建属性节点。
- 此时发现, 虽然创建出新的 div 了, 但是 div 并没有显示在页面上. 这是因为新创建的节点并没有加入到 DOM 树中.
5.2插入节点到 dom 树中
1 使用 appendChild 将节点插入到指定节点的最后一个孩子之后
element.appendChild(aChild)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>js</title>
</head>
<body>
<div class="container"></div>
<script>
let div = document.createElement('div');
div.innerHTML = '这是一段文字';
div.style = 'font-size: 40px';
div.id = 'mydiv';
let container = document.querySelector('.container');//获取containner类元素
container.appendChild(div);//加入containner结点的子节点中
</script>
</body>
</html>
示例
2.使用 insertBefore 将节点插入到指定节点之前.
var insertedNode = parentNode.insertBefore(newNode, referenceNode)
insertedNode
被插入节点(newNode)parentNode
新插入节点的父节点newNode
用于插入的节点referenceNode
:newNode将要插在这个节点之前
如果referenceNode为nul则,newNode将被插入到子节点的末尾.
referenceNode 引用节点不是可选参数
示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>js</title>
</head>
<body>
<ol id = 'container'>
<li>列表1</li>
<li>列表2</li>
<li>列表3</li>
<li>列表4</li>
</ol>
<script>
let container = document.querySelector('#container');
let li = document.createElement('li');
li.innerHTML='列表0';
container.insertBefore(li,container.children[0]);
</script>
</body>
</html>
六、删除节点
使用 removeChild 删除子节点
oldChild = element.removeChild(child);
- child 为待删除节点
- element 为 child 的父节点
- 返回值为该被删除节点
- 被删除节点只是从 dom 树被删除了, 但是仍然在内存中, 可以随时加入到 dom 树的其他位置。
- 如果上述child节点不是element节点的子节点,则该方法会抛出异常。
代码案例1: 猜数字
效果图’
首先要说一下JS中随机数实现
N = Math.random();
N的范围时[0,1);
我们需要1-100的整数,那么只需要再将N*100+1即可。
但是这里的N还是小数,所以还需要用parseINT转一下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>js</title>
</head>
<body>
<button id="reset">重新开始</button>
<br>
请输入你要猜的数字:
<input type="text" id="input_number">
<button id="button_input">输入</button>
<br>
已经猜的次数:<span id="count">0</span>
<br>
结果:<span id="result"></span>
</body>
<script>
let button_reset = document.querySelector('#reset');
let intput_number = document.querySelector('#input_number');
let button_input = document.querySelector('#button_input');
let count = document.querySelector('#count');
let result = document.querySelector('#result');
let number = (parseInt(Math.random()*100)+1);
console.log(number);
button_input.onclick = function(){
count.innerHTML = parseInt(count.innerHTML)+1;
if(parseInt(intput_number.value)== number) {
result.innerHTML = '猜对了!'
}
if(parseInt(intput_number.value)< number){
result.innerHTML = '猜小了!'
}
if(parseInt(intput_number.value)> number){
result.innerHTML = '猜大了!'
}
}
button_reset.onclick = function(){
number = (parseInt(Math.random()*100)+1);
console.log(number);
result.innerHTML = '';
count.innerHTML = 0;
}
</script>
</html>
代码案例2: 表白墙
下面是基本代码
<!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>表白墙</title>
<style>
/* * 通配符选择器, 是选中页面所有元素 */
* {
/* 消除浏览器的默认样式. */
margin: 0;
padding: 0;
box-sizing: border-box;
}
.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 class="row">
xxx 对 xx 说 xxxx
</div> -->
</div>
<script>
// 实现提交操作. 点击提交按钮, 就能够把用户输入的内容提交到页面上显示.
// 点击的时候, 获取到三个输入框中的文本内容
// 创建一个新的 div.row 把内容构造到这个 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>
至此我们的webapi就说到这里啦