API和WebAPI
DOM (文档对象模型)
定义
DOM树
获取元素
根据ID获取
<body>
<div id="date">2020-9-6</div>
<script>
var res = document.getElementById('date')
console.log(res);
console.dir(res)
</script>
</body>
根据标签名
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
<script>
var res = document.getElementsByTagName('li')
console.log(res);
console.dir(res)
</script>
</body>
输出:
使用这个方法可以得到文档里所有的li,但有时我们仅需要对特定标签中的li进行处理,比如下面这种情况:
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
<ul id="target">
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
</ul>
<script>
var target = document.getElementById('target');
var res = target.getElementsByTagName('li');
console.log(res);
console.dir(res)
</script>
</body>
我们想获得target里面的li,那么可以:
- 先获得target对应的标签:var target = document.getElementById(‘target’);
- 然后根据这个标签来获取里面的li:var res = target.getElementsByTagName(‘li’);
根据类名获得
<body>
<div class="box">1</div>
<div class="box">2</div>
<script>
var res = document.getElementsByClassName('box')
console.log(res);
console.dir(res)
</script>
</body>
也可以使用querySeclector来选择,只需要在括号里指明选择器就好了(是类选择器就加.,是id选择器就加#,标签无需加),但只能选择第一个标签:
<body>
<div class="box">1</div>
<div class="box">2</div>
<div id="nav">
<ul>
<li>1</li>
<li>2</li>
</ul>
</div>
<script>
var res = document.getElementsByClassName('box')
console.log(res);
// console.dir(res)
var res2 = document.querySelector('#nav')
console.log(res2);
</script>
</body>
结果:
如果想选择所有标签,可以用:querySelectorAll。
注意,这个querySelector涉及到兼容性的问题
特殊元素获取
事件
- 这个事件要在谁身上发生
- 什么情况下会触发
- 触发后的动作是怎样的
常见的鼠标事件
操作元素
改变元素内文本信息
innerText有弊端,即它不识别html结构,但innerHTML可以。
我们可以在进行一些动作(比如说鼠标经过标签)时更改标签的内容:
<body>
<button>显示当前日期</button>
<div>请点击</div>
<p></p>
<script>
var btn = document.querySelector('button')
var date = document.querySelector('div')
btn.onclick = function() {
date.innerText = getdate()
}
function getdate() {
var date = new Date()
var year = date.getFullYear()
var month = date.getMonth() + 1
var day = date.getDate()
return '今天是' + year + '年' + month + '月' + day + '日'
}
var pp = document.querySelector('p')
pp.innerText = getdate()
</script>
</body>
我们在点击按钮后,让div标签显示当前日期,但p标签不需要点击就可以显示日期。
这个innerText/HTML可以修改标签中内容
改变元素属性
我们还可以改变元素的属性,比如说当鼠标点击一个按钮时改变显示的图片:
<body>
<button class="btn1">点我呗</button>
<button class="btn2">点我吧</button>
<br>
<img src="./images/1.jpg" alt="">
<script>
var b1 = document.querySelector('.btn1')
var b2 = document.querySelector('.btn2')
var p = document.querySelector('img')
b1.onclick = function() {
p.src = './images/1.jpg'
}
b2.onclick = function() {
p.src = './images/2.jpg'
}
</script>
</body>
结果:
其实只要是获取到了目标对象(比如说本例中的img),那么这个标签所具有的属性都可以修改。
一个案例 根据不同的时间做对应的动作
<body>
<img src="./images/1.jpg" alt="">
<div>早上好</div>
<script>
var pic = document.querySelector('img')
var word = document.querySelector('div')
// 开始获取小时
var date = new Date()
var h = date.getHours()
if (h < 12) {
pic.src = './images/1.jpg'
word.innerHTML = '上午好'
}
else if (h < 18) {
pic.src = './images/2.jpg'
word.innerHTML = '下午好'
}
else {
pic.src = './images/3.jpg'
word.innerHTML = '晚上好'
}
</script>
</body>
表单元素的属性操作
上一节说的是常规元素的属性操作,但表单有些特殊,如果想改变表单中的文字,用innerText/HTML是不行的,要改变value的值才可以:
<body>
<button class="btn">点我试试</button>
<input type="text" value="我是通过value添加的">
<script>
var btn = document.querySelector('.btn')
var input = document.querySelector('input')
btn.onclick = function() {
input.value = '我被点击了'
this.disabled = true
}
</script>
</body>
其中,this.disabled = true的意思是将按钮设置为不可用状态(也就是点击一次后就不可用了)。
案例 实现密码框的明文与隐藏效果
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.box {
width: 300px;
border-bottom: 1px solid #ccc;
}
.box input {
margin-top: 20px;
width: 250px;
height: 30px;
outline: none;
border: 0;
}
</style>
</head>
<body>
<div class="box">
<button class="btn">点我显示/关闭密码</button>
<input type="password" name="" id="">
</div>
<script>
var btn = document.querySelector('.btn')
var input = document.querySelector('input')
btn.onclick = function() {
input.type = 'text'
}
</script>
</body>
修改样式
不仅可以对标签本身进行修改,还可以对样式进行修改(大小、颜色等)。
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.box {
width: 200px;
height: 200px;
background-color: red;
}
</style>
</head>
<body>
<div class="box"></div>
<script>
var box = document.querySelector('.box')
box.onclick = function() {
box.style.backgroundColor = 'blue'
}
</script>
</body>
上述代码可以实现点击标签改变其颜色。
案例 关闭广告/二维码
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.box {
position: relative;
width: 100px;
height: 130px;
/* background-color: #ccc; */
margin: 20px auto;
border: 1px solid #ccc;
}
img {
width: 100%;
height: 100%;
}
.btn_close {
width: 14px;
height: 14px;
border: 1px solid black;
position: absolute;
top: -1px;
left: -16px;
text-align: center;
font-style: normal;
line-height: 14px;
color: red;
cursor: pointer;
}
</style>
</head>
<body>
<div class="box">
<img src="./images/pvp.png" alt="">
<i class="btn_close">x</i>
</div>
<script>
var btn = document.querySelector('.btn_close');
var box = document.querySelector('.box');
btn.onclick = function() {
box.style.display = 'none';
}
</script>
</body>
点击红色叉后:
案例 使用js快速搞定精灵图
我没搞到淘宝的原图…还是看视频吧:https://www.bilibili.com/video/BV167411p7hi?p=21
案例 输入框
- 默认状态下,输入框中有文字
- 当点击输入框时,默认文字消失
- 当鼠标离开输入框且没输入文字时,输入框恢复默认文字
- 当鼠标离开输入框且输入了文字时,输入框显示输入的文字
<body>
<input type="text" value="笔记本电脑">
<script>
var input = document.querySelector('input')
input.onfocus = function() {
if (this.value == "笔记本电脑") {
input.value = ""
}
this.style.color = '#333'
}
input.onblur = function() {
if (input.value == "") {
input.value = "笔记本电脑"
}
input.style.color = 'red'
}
</script>
</body>
更方便的修改样式
按之前所说,js可以修改相应对象的样式:
- element.style.fontSize:20px
但当修改的样式过多的时候,这么一行一行写就太麻烦了,因此引入了更方便的方式。
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
div {
margin: 100px auto;
width: 200px;
height: 200px;
background-color: skyblue;
transition: all 1s;
}
.change {
border-radius: 50%;
background-color: red;
}
</style>
</head>
<body>
<div>123</div>
<script>
var tar = document.querySelector('div')
tar.onclick = function() {
this.className = 'change'
}
</script>
</body>
我们把鼠标点击后的变化做成css样式:change,在js里面,当点击div标签时,将change类名赋值给div对象,那么div也就有了一个类change。
注意,这种方式会将div已经有的类覆盖掉,因此如果div之前就有类名,要使用如下方式:
- this.className = ‘原来已有的类(可能是多个) change’
案例 密码框
下面的代码可以对输入的密码进行简单的验证,如果位数不正确就会报错,更复杂的筛选规则后面再说。
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.pwd {
width: 600px;
margin: 100ox auto;
}
.tip {
display: inline-block;
color: #999;
padding-left: 15px;
}
</style>
</head>
<body>
<div class="pwd">
设置密码:<input type="password" name="" id="input_pwd">
<p class="tip">请输入密码(长度大于6位)</p>
</div>
<script>
var tip = document.querySelector('.tip')
var input = document.querySelector('#input_pwd')
input.onblur = function() {
if (input.value.length <= 6 ) {
console.log('密码不符合规范,请重新输入');
tip.innerHTML = '密码不符合规范,请重新输入'
tip.style.color = 'red'
}
else {
tip.innerHTML = '格式正确!'
tip.style.color = 'green'
}
}
</script>
</body>
案例 下拉菜单
以微博为例,简单的实现了下拉菜单(做的太粗糙了…)
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
padding: 0;
margin: 0;
}
li {
list-style-type: none;
height: 30px;
border-bottom: 1px orangered solid;
font-size: 14px;
color: #4c4c4c;
}
a {
text-decoration: none;
color: black;
}
.nav {
height: 30px;
width: 80px;
background-color: #fff;
line-height: 30px;
}
.head {
height: 30px;
}
.head a {
display: block;
padding: 0 15px;
}
.head:hover {
background-color: #f1f1f1;
}
.head a::after {
content: "";
display: inline-block;
width: 6px;
height: 6px;
margin-left: 7px;
margin-bottom: 2px;
border-bottom: 1px solid #ff8400;
border-right: 1px solid #ff8400;
transform: rotate(45deg);
}
.menu {
display: none;
width: 80px;
border-left: 1px orangered solid;
border-right: 1px orangered solid;
}
.menu a {
display: block;
padding: 0 3px 0 15px;
}
.menu li:hover {
background-color: #ffcc80;
}
</style>
</head>
<body>
<div class="nav">
<div class="head"><a href="#">微博</a></div>
<div class="menu">
<ul>
<li><a href="#">私信</a></li>
<li><a href="#">评论</a></li>
<li><a href="#">@我</a></li>
</ul>
</div>
</div>
<script>
var target = document.querySelector('.head')
var menu = document.querySelector('.menu')
target.onmouseover = function() {
menu.style.display = 'block'
}
target.onmouseout = function() {
menu.style.display = 'none'
}
menu.onmouseover = function() {
menu.style.display = 'block'
}
menu.onmouseout = function() {
menu.style.display = 'none'
}
</script>
</body>
案例 更换背景图片
我们想点击屏幕上的某一张图片,然后将网页背景换成相应的图片。
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
padding: 0;
margin: 0;
}
li {
list-style: none;
}
body {
background: url(./images/1.jpg) no-repeat center top;
}
.change {
margin: 100px auto;
background-color: #ccc;
width: 410px;
height: 60px;
padding-top: 3px;
}
.change li {
float: left;
margin: 0 1px;
cursor: pointer;
}
.change img {
width: 100px;
height: 56.23px;
}
</style>
</head>
<body>
<ul class="change">
<li><img src="./images/1.jpg" alt=""></li>
<li><img src="./images/2.jpg" alt=""></li>
<li><img src="./images/3.jpg" alt=""></li>
<li><img src="./images/4.jpg" alt=""></li>
</ul>
<script>
var btns = document.querySelectorAll('img')
for (var i = 0; i < btns.length; i++) {
btns[i].onclick = function () {
document.body.style.backgroundImage = 'url(' + this.src + ')'
}
}
</script>
</body>
案例 全选功能
https://www.bilibili.com/video/BV167411p7hi?p=30
自定义属性
除了标签默认提供的属性之外,我们还可以自己定义属性:
<body>
<div id="first"></div>
<script>
// 获取
var div = document.querySelector('div')
console.log(div.id);
console.log(div.getAttribute('id'));
// 设置
div.id = 'second'
// div.index = '1'
div.setAttribute('index', '1')
div.setAttribute('id', 'third')
console.log(div.id);
console.log(div.getAttribute('index'));
// 移除
div.removeAttribute('index')
</script>
</body>
注意,我尝试了用div.index = '1’这种方式设置新的属性,使用div.index会有输出,但div.getAttribute(‘index’)就显示null,且网页中的结构并没有index属性,而使用div.setAttribute(‘index’, ‘1’)则可以在html文件中显示,但使用div.index输出会显示undefined
案例 tab栏切换
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
padding: 0;
margin: 0;
}
.tab {
width: 700px;
margin: 100px auto;
}
.tab_list {
height: 39px;
}
.tab_list .current {
background-color: #c81623;
font-size: 16px;
color: #fff;
}
.tab_list li {
float: left;
height: 39px;
line-height: 39px;
list-style: none;
padding: 0 20px;
text-align: center;
cursor: pointer;
}
.item {
display: none;
}
</style>
</head>
<body>
<div class="tab">
<div class="tab_list">
<ul>
<li class="current">商品介绍</li>
<li>规格与包装</li>
<li>售后保障</li>
<li>商品评价(4788)</li>
<li>手机社区</li>
</ul>
</div>
<div class="tab_con">
<div class="item" style="display: block;">
商品介绍模块内容
</div>
<div class="item">
规则包装模块内容
</div>
<div class="item">
售后保障模块内容
</div>
<div class="item">
商品评价(4788)模块内容
</div>
<div class="item">
手机社区模块内容
</div>
</div>
</div>
<script>
var tab_list = document.querySelector('.tab_list')
var lis = tab_list.querySelectorAll('li')
var items = document.querySelectorAll('.item')
for (var i = 0; i < lis.length; i ++)
{
lis[i].setAttribute('index', i)
lis[i].onclick = function() {
// 第一部分,目标选项卡变色
for (var i = 0; i < lis.length; i++)
{
lis[i].className = ''
items[i].style.display = 'none'
}
this.className = 'current'
// 第二部分,点击选项卡显示相应内容
var index = this.getAttribute('index')
// for (var j = 0; j < lis.length; j++)
// {
// items[j].style.display = 'none'
// }
items[index].style.display = 'block'
}
}
console.log(lis);
</script>
</body>
自定义属性规范
节点操作
父节点
子节点
举例来说,我们有如下代码:
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
<ol>
<li></li>
<li></li>
<li></li>
<li></li>
</ol>
如果我们想获取ul中所有的li,那么按照之前的做法应该是:
- var ul = document.querySelector(‘ul’)
- var lis = ul.querySelectorAll(‘li’)
这样略显麻烦,我们可以用子节点的方式:
- var ul = document.querySelector(‘ul’)
- console.log(ul.childNodes)
但我们观察结果:
发现除了我们想要的li之外,还有奇怪的东西混进来了:text。
原因是我们得到的结果包含文本节点,可通过如下代码过滤:
<script>
// DOM 方法
var ul = document.querySelector('ul')
var lis = ul.querySelectorAll('li')
// 子节点
for (var i = 0; i < ul.childNodes.length; i++)
{
if (ul.childNodes[i].nodeType == 1)
{
console.log(ul.childNodes[i]);
}
}
console.log(ul.childNodes);
// console.log(ul.children);
</script>
但这样还是麻烦啊!说好的更方便呢?我们可以用如下方式:
这下可以看看输出结果,是我们想要的:
接着走:
现在,我们想获取ol中第一个和最后一个节点,按照之前的做法要通过[0]之类的来访问,但我们有其它方式了:
但这么做还是有包含文本节点的毛病,因此又有如下做法:
但如上做法又有兼容性问题,我们可以通过下面方法解决:
- ol.children[0]/ol.children[ol.children.length - 1]
案例
P41,等素材下载好了再看看
兄弟节点
上面这两个也是有那个毛病:把文本节点也算在内,那么就有如下方法:
但这又有兼容性的问题
里面的1是指元素的nodeType,若为标签元素则为1。
创建节点
有些情况,比如说给帖子留言时,会生成一个新的标签,那么就需要创建节点:
添加节点
但只是创建还不够,还要将这个节点添加到某个位置:
<body>
<ul>
<li>ori node</li>
</ul>
<script>
var li_after = document.createElement('li')
var ul = document.querySelector('ul')
var li_before = document.createElement('li')
li_after.innerHTML = '456'
ul.append(li_after)
ul.insertBefore(li_before, ul.children[1])
</script>
</body>
案例 留言功能
<body>
<textarea name="" id="content" cols="30" rows="10">123</textarea>
<button class="btn">提交</button>
<ul>
</ul>
<script>
var btn = document.querySelector('.btn')
var con = document.querySelector('#content')
var ul = document.querySelector('ul')
btn.onclick = function() {
if (con.value == "") {
alert('您输入的内容为空!')
return false
}
else {
var li = document.createElement('li')
li.innerHTML = con.value
ul.insertBefore(li, ul.children[0])
}
}
</script>
</body>
删除节点
和前面的很类似了。
案例 留言功能的改进
我们在这里添加删除留言的功能。
<body>
<textarea name="" id="content" cols="30" rows="10">123</textarea>
<button class="btn">提交</button>
<ul>
</ul>
<script>
var btn = document.querySelector('.btn')
var con = document.querySelector('#content')
var ul = document.querySelector('ul')
btn.onclick = function () {
if (con.value == "") {
alert('您输入的内容为空!')
return false
} else {
var li = document.createElement('li')
li.innerHTML = con.value + '<a href="javascript:;" target="_blank" rel="external nofollow" >删除</a>'
ul.insertBefore(li, ul.children[0])
var as = document.querySelectorAll('a')
for (var i = 0; i < as.length; i++) {
as[i].onclick = function () {
console.log('1');
ul.removeChild(this.parentNode)
}
}
}
}
</script>
</body>
克隆节点
案例 动态添加/删除表格
我们想动态的生成上述表格,并且点击删除后可以将对应的行删除。
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
table {
width: 500px;
margin: 100px auto;
text-align: center;
border-collapse: collapse;
}
td,
th {
border: 1px solid #333;
}
thead tr {
height: 40px;
background-color: #ccc;
}
</style>
</head>
<body>
<table>
<thead>
<tr>
<th>姓名</th>
<th>科目</th>
<th>成绩</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr>
<td>A</td>
<td>JS</td>
<td>100</td>
<td><a href="#">删除</a></td>
</tr>
</tbody>
</table>
<script>
var datas = [
{
name:'B',
subject:'JS',
score: 97
},
{
name:'C',
subject:'JS',
score: 95
},
{
name:'D',
subject:'JS',
score: 88
}
]
var tbody = document.querySelector('tbody')
for (var i = 0; i < datas.length; i++) {
// 创建行
var tr = document.createElement('tr')
tbody.appendChild(tr)
// 创建单元格 k 是属性名
for (var k in datas[i]) {
var td = document.createElement('td')
td.innerHTML = datas[i][k]
tr.appendChild(td)
}
// 删除选项的添加
var td = document.createElement('td')
td.innerHTML = '<a href="#" target="_blank" rel="external nofollow" >删除</a>'
tr.appendChild(td)
}
// 删除功能的实现
var as = document.querySelectorAll('a')
for (var i = 0; i < as.length; i++){
as[i].onclick = function() {
// 点击a后删除那行
tbody.removeChild(this.parentNode.parentNode)
}
}
</script>
</body>
三种动态创建元素方法的区别 (面试题)
数组形式拼接代码:
回顾
- 创建
- 增
- 删
- 改
- 查
- 属性操作
- 事件操作