Javascript之DOM
DOM
DOM:(document object mode)文档对象模型。DOM为文档提供了结构化表示,并定义了如何通过脚本来访问文档结构。
目的就是为了能让js操作html元素而制定的一个规范
DOM是由节点组成的:HTML加载完毕,渲染引擎会在内存中把HTML文档,生成一个DOM树
操作网页上的元素的API。比如让盒子移动、变色、轮播图等。
上图可知,在HTML当中,一切都是节点:(非常重要)
- 元素节点:HTML标签。
- 文本节点:标签中的文字(比如标签之间的空格、换行)
- 属性节点::标签的属性。
整个html文档就是一个文档节点。所有的节点都是Object。
object节点维护的内容
dom操作的内容
节点查找
直接查找
根据ID查找
永远只会找到一个标签
// obj = document.getElementById('元素的id') 永远只会找到一个标签
var dar = document.getElementById('d1');
console.log(dar)
根据类名查找
永远得到一个数组
var objs = document.getElementsByClassName('foo');
console.log(objs[0]);
console.log(objs[1]);
根据标签查找
永远得到一个数组
var objs = document.getElementsByTagName('div');
console.log(objs[0])
console.log(objs[1])
console.log(objs[2])
间接查找
节点之间的关系是以属性的方式存在的
找父亲
var p_obj = document.getElementsByClassName('foo')[0]
console.log(p_obj.parentElement);
找儿子
var objs = document.getElementById('d1');
console.log(objs.children); // objs的子标签
console.log(objs.firstElementChild); // objs的第一个子标签
console.log(objs.lastElementChild); // objs的最后一个子标签
找哥哥
var p_obj = document.getElementsByClassName('foo')[0];
dac = p_obj.nextElementSibling // p_obj的下一个同级元素
console.log(dac.previousElementSibling); // dac的上一个同级元素
找弟弟
var p_obj = document.getElementsByClassName('foo')[0];
console.log(p_obj.nextElementSibling); // p_obj的下一个同级元素
操作节点
// 创建节点
obj = document.createElement('p')
<p></p>
obj.innderText = 'p标签'
<p>p标签</p>
// 添加节点
父节点.appendChild(子节点对象)
父节点.insertBefore(要添加的子对象,参考节点对象)
// 删除节点
父节点.removeChild(子节点对象)
// 克隆节点
节点.cloneNode() 只拷贝一层
节点.cloneNode(True) 拷贝所有子节点
// 替换节点
父节点.replaceChild(新对象,旧子节点)
创建标签
obj = document.createElement('p'); // 创建一个p标签
obj.innerText = '我是一个p标签'; // 给创建的p标签插入值
插入节点
- appendChild 在查找到的元素最后一个元素的位置追加
- insertBefore 在查找到的元素前插入
// appendChild
var p = document.createElement('p');
p.innerText = '我是一个p标签'
var obj = document.getElementById('d1');
obj.appendChild(p); // 将p标签插入到obj子标签的最后位置
// insertBefore
var p = document.createElement('p');
p.innerText = '我是一个p标签'
var obj = document.getElementById('d1');
var p2 = obj.firstElementChild;
obj.insertBefore(p,p2); // 将p标签插入到p2标签前
删除子节点
var obj = document.getElementById('d1');
// var las_obj = obj.lastElementChild;
var las_obj = document.getElementsByTagName('a')[0];
obj.removeChild(las_obj); // 父节点 删除 las_obj
删除自己
var a_obj = document.getElementsByTagName('a')[0];
var di_obj = a_obj.parentElement;
di_obj.removeChild(a_obj);
复制节点
var obj = document.getElementById('d1');
var new_obj = obj.cloneNode(true);
// 不加true 默认只会浅拷贝,例如只会拷贝匹配到的这一行,而不会拷贝这一行的子元素
obj.appendChild(new_obj);
替换节点
var new_p = document.createElement('p');
new_p.innerText = '我是一个新的p标签'
var obj = document.getElementById('d1');
var p_obj = obj.firstElementChild;
// 父节点.replaceChild(新节点,旧节点)
obj.replaceChild(new_p,p_obj);
操作节点内的文本
// innerText pobj.innerText = '<a>我是一个a标签</a>'
// innerText 只人文本 html是不认识的
var new_p = document.createElement('p');
new_p.innerText = '<p>我是一个新的p标签</p>'
console.log(new_p);
// innerHTML
var new_p = document.createElement('p');
new_p.innerHTML = '<a href="http://www.baidu.com">chaojibaidu</a>'
console.log(new_p);
操作值
var obj = document.getElementsByTagName('input')[0];
obj.value; // 获取值
"alexvalue"
obj.value = 'cccc'; // 设置值
操作属性
// obj.setAttribute('属性名','属性值')
// obj.getAttribute('属性名')
// obj.removeAttribute('属性名')
var obj = document.getElementById('mi');
// 设置属性
obj.setAttribute('href','http://www.baidu.com')
// 删除属性
obj.removeAttribute('href')
// 获取属性的值
console.log(obj.getAttribute('href'));
操作类
// LOW方法
document.getElementsByTagName('li')[1].setAttribute('class','c_li');
var obj = document.getElementById('mi');
// 查看类的数组
obj.classList;
// 类名的数组中追加
obj.classList.add('c_li2');
// 类名数组中删除
obj.classList.remove('c_li');
// 类名数组中是否存在 存在返回true 不存在返回false
obj.classList.contains('c_li');
true
// 类名数组中存在就删除,没有就加上
obj.classList.toggle('c_li');
true
obj.classList.toggle('c_li');
false
操作样式
// obj.style.样式名 = 样式值
var obj = document.getElementById('mi');
obj.style.backgroundColor = 'red';
"red"
例子:红绿灯
<!DOCTYPE html>
<html lang="zh_CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Green</title>
<style>
.outer{
border:solid darkgrey 5px;
display:inline-block;
padding:5px;
border-radius:10px;
}
.light{
float:left;
height:100px;
width:100px;
border-radius:50%;
background-color:lightgray;
margin-left:5px;
}
.clearfix:after{
content:'';
clear:both;
display: inline-block;
}
.red{
background-color:red;
}
.yellow{
background-color:yellow;
}
.green{
background-color:green;
}
</style>
</head>
<body>
<div class="outer">
<div class="container">
<div class="light red"></div>
<div class="light"></div>
<div class="light"></div>
</div>
</div>
</body>
<script>
function fn(){
var lights = document.getElementsByClassName('light');
if (lights[0].classList.contains('red')){
lights[0].classList.remove('red');
lights[1].classList.add('yellow');
}else if (lights[1].classList.contains('yellow')){
lights[1].classList.remove('yellow');
lights[2].classList.add('green');
}else{
lights[2].classList.remove('green');
lights[0].classList.add('red');
}
}
setInterval(fn,1000)
</script>
</html>
事件
JS是以事件驱动为核心的一门语言。
事件源:引发后续事件的html标签。
事件:js已经定义好了(见下图)
事件驱动程序:对样式和html的操作。也就是DOM。
代码书写步骤如下:(重要)
(1)获取事件源:document.getElementById(“box”); //类似与ios语言的 UIButton *adBtn = [UIButton buttonWithType:UIButtonTypeCustom];
(2)绑定事件: 事件源box.事件onclick = function(){ 事件驱动程序 };
(3)书写事件驱动程序:关于DOM的操作
代码示例:
<body>
<div id="box1"></div>
<script type="text/javascript">
// 1、获取事件源
var div = document.getElementById("box1");
// 2、绑定事件
div.onclick = function () {
// 3、书写事件驱动程序
alert("我是弹出的内容");
}
</script>
</body>
常见事件如下:
3中绑定事件的方式:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div>
<ul id="items">
<li>item1</li>
<li>item2</li>
<li>item3</li>
</ul>
</div>
<button onclick="fn()">按钮1</button>
<button id="bt2">按钮2</button>
<button id="bt3">按钮3</button>
<!-- <bottom>按钮1</bottom> -->
</body>
<script>
var btn2 = document.getElementById('bt2');
btn2.onclick = fn;
function fn(){
var obj = document.getElementById('items');
var liobj = document.createElement('li');
liobj.innerText = '插入的li标签'
obj.appendChild(liobj);
}
var bt3 = document.getElementById('bt3');
bt3.onclick = function fn() {
var obj = document.getElementById('items');
var liobj = document.createElement('li');
liobj.innerText = '插入的li标签'
obj.appendChild(liobj);
}
</script>
</html>
下面针对事件的三要素,进行分别介绍。
1、获取事件源(DOM节点的获取)
示例:
1.模态框案例
需求:打开网页时有一个普通的按钮,点击当前按钮显示一个背景图,中心并弹出一个弹出框,点击X的时候会关闭当前的模态框
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
*{
padding: 0;
margin: 0;
}
html,body{
height: 100%;
}
#box{
width: 100%;
height: 100%;
background: rgba(0,0,0,.3);
}
#content{
position: relative;
top: 150px;
width: 400px;
height: 200px;
line-height: 200px;
text-align: center;
color: red;
background-color: #fff;
margin: auto;
}
#span1{
position: absolute;
background-color: red;
top: 0;
right: 0;
width: 30px;
height: 30px;
line-height: 30px;
text-align: center;
color: #fff;
}
</style>
</head>
<body>
<button id="btn">弹出</button>
</body>
<script type="text/javascript">
//获取dom元素 1.获取事件源
var oBtn = document.getElementById('btn');
//创建弹出模态框的相关DOM对象
var oDiv = document.createElement('div');
var oP = document.createElement('p');
var oSpan = document.createElement('span');
// 设置属性
oDiv.id = 'box';
oP.id = 'content'
oP.innerHTML = '模态框成功弹出'
oSpan.innerHTML = 'X';
oSpan.id = 'span1'
// 追加元素
oDiv.appendChild(oP);
oP.appendChild(oSpan);
// 点击弹出按钮 弹出模态框
oBtn.onclick = function(){
//动态的添加到body中一个div
this.parentNode.insertBefore(oDiv,oBtn)
}
// 点击X 关闭模态框
oSpan.onclick = function(){
// 移除oDiv元素
oDiv.parentNode.removeChild(oDiv)
}
</script>
</html>
2.Select选择框
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<select name="province" id="province">
<option value="0" selected>请选择省</option>
</select>
<select name="city" id="city">
<option>请选择市:</option>
</select>
</body>
<script>
data = {"河北": ["廊坊", "邯郸"], "北京": ["朝阳区", "海淀区"], "山东": ["威海市", "烟台市"]}
var select1 =document.getElementById('province')
for(i in data){
var option = document.createElement('option')
option.innerText = i
select1.appendChild(option)
}
select1.onchange = function () {
var select2 =document.getElementById('city')
select2.innerText = null
var choosed = select1.options[this.options.selectedIndex].innerText
for(var i=0;i<data[choosed].length;i++){
var option = document.createElement('option')
option.value = i
option.innerText = data[choosed][i]
select2.appendChild(option)
}
}
</script>
</html>
3.Tab选项卡
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
*{
padding: 0;
margin: 0;
}
ul{
list-style: none;
}
#tab{
width: 480px;
margin: 20px auto;
border: 1px solid red;
}
ul{
width: 100%;
overflow: hidden;
}
ul li{
float: left;
width: 160px;
height: 60px;
line-height: 60px;
text-align: center;
background-color: #cccccc;
}
ul li a{
text-decoration: none;
color:black;
}
li.active{
background-color: red;
}
p{
display: none;
height: 200px;
text-align: center;
line-height: 200px;
background-color: red;
}
p.active{
display: block;
}
</style>
</head>
<body>
<div id="tab">
<ul>
<li class="active">
<a href="#">首页</a>
</li>
<li>
<a href="#">新闻</a>
</li>
<li>
<a href="#">图片</a>
</li>
</ul>
<p class="active">首页内容</p>
<p>新闻内容</p>
<p>图片内容</p>
</div>
</body>
<script type="text/javascript">
window.onload = function(){
// //需求:鼠标放到上面的li上,li本身变色(添加类),对应的p也显示出来(添加类);
//思路:1.点亮上面的盒子。 2.利用索引值显示下面的盒子。
var tabli = document.getElementsByTagName('li');
var tabContent = document.getElementsByTagName('p')
for(var i = 0; i < tabli.length; i++){
// 绑定索引值(新增一个自定义属性:index属性)
tabli[i].index = i;
tabli[i].onclick = function(){
// 1.点亮上面的盒子。 2.利用索引值显示下面的盒子。(排他思想)
for(var j = 0; j < tabli.length; j++){
tabli[j].className = '';
tabContent[j].className = '';
}
this.className = 'active'
tabContent[this.index].className = 'active';//【重要代码】
}
}
}
</script>
</html>
4.简易留言板
需求:当在textarea中输入内容,点击留言按钮,会添加到浏览器中,效果图如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>留言板</title>
<style type="text/css">
*{
padding: 0;
margin: 0;
}
.close{
display: inline-block;
width: 20px;
height: 20px;
line-height: 20px;
text-align: center;
cursor: pointer;
background-color: rgba(0,0,0,.1);
margin-left: 20px;
}
</style>
</head>
<body>
<h1>简易留言板</h1>
<div id="box">
<!--<ul>
</ul>-->
</div>
<textarea id="msg"></textarea>
<input type="button" id="btn" value="留言"/>
<button onclick="sum()">统计</button>
</body>
<script type="text/javascript">
// 0 将ul标签添加到div#box标签中
var oUl = document.createElement('ul');
var oBox = document.getElementById('box');
oBox.appendChild(oUl);
var oBtn = document.getElementById('btn');
var oMsg = document.getElementById('msg')
// 控制留言的总数量
var count = 0;
oBtn.onclick = function(){
// 点击留言按钮事件操作
// 1.创建li标签
var oLi = document.createElement('li');
//2.设置内容
oLi.innerHTML = oMsg.value + "<span class='close'>X</span>"
// 3.如果想在插入的第一个li获取的前面继续添加li标签
//3.1获取li标签
var olis = document.getElementsByTagName('li');
//3.2 如果是第一次添加的li标签,则直接添加到ul的后面
if(olis.length == 0){
oUl.appendChild(oLi);
count++;
}else{
// 3.3 如果不是第一次添加的li标签,则插入到第一个li标签的前面
oUl.insertBefore(oLi,olis[0]);
count++;
}
// 4.添加完成之后 清空textarea的值
oMsg.value = '';
// 5.点击X的时候删除当前的一条数据
//5.1先获取所有的X
var oSpans = document.getElementsByTagName('span');
// 5.2for循环 对所有的X添加点击事件
for(var i = 0; i< oSpans.length; i++){
oSpans[i].onclick = function(){
// 5.3 移除当前的li标签
oUl.removeChild(this.parentNode)
count--;
}
}
}
function sum(){
alert('一共发布了'+count+'条留言');
}
</script>
</html>