文章目录
1 DOM概念
概念
所谓DOM,全称 Docuemnt Object Model 文档对象模型,毫无疑问,此时要操作对象,什么对象?文档对象
在文档中一切皆对象,比如html,body,div,p等等都看做对象,那么我们如何来点击某个盒子让它变色呢?
DOM 为文档提供了结构化表示,并定义了如何通过脚本来访问文档结构。目的其实就是为了能让js操作html元素而制定的一个规范。
解析过程
HTML加载完毕,渲染引擎会在内存中把HTML文档,生成一个DOM树,getElementById是获取内中DOM上的元素节点。然后操作的时候修改的是该元素的属性。
2 DOM树(一切皆是节点)
上图可知,在HTML当中,一切都是节点:(非常重要)
- 元素节点:HMTL标签。
- 文本节点:标签中的文字(比如标签之间的空格、换行)
- 属性节点::标签的属性
整个html文档就是一个文档节点。所有的节点都是Object。
3 DOM可以做什么
- 找对象(元素节点)
- 设置元素的属性值
- 设置元素的样式
- 动态创建和删除元素
- 事件的触发响应:事件源、事件、事件的驱动程序
4 DOM的结构
- 获取文档对象:document
- 获取html:document.documentElement
- 获取body: document.body
5 获取其它DOM(事件源)的三种方式
var oDiv1 = document.getElementById("box1"); //方式一:通过id获取单个标签
var oDiv2 = document.getElementsByTagName("div")[0]; //方式二:通过 标签名 获得 标签数组,所以有s
var oDiv3 = document.getElementsByClassName("box")[0]; //方式三:通过 类名 获得 标签数组,所以有s
6 事件
JS是事件驱动为核心的一门语言
7 事件的三要素
事件的三要素:事件源、事件、事件驱动程序。
比如,我用手去按开关,灯亮了。这件事情里,事件源是:手。事件是:按开关。事件驱动程序是:灯的开和关。
再比如,网页上弹出一个广告,我点击右上角的X
,广告就关闭了。这件事情里,事件源是:X
。事件是:onclick。事件驱动程序是:广告关闭了。
于是我们可以总结出:谁引发的后续事件,谁就是事件源。
总结如下:
- 事件源:引发后续事件的html标签。
- 事件:js已经定义好了(见下图)。
- 事件驱动程序:对样式和html的操作。也就是DOM。
代码书写步骤如下:(重要)
- (1)获取事件源:
document.getElementById(“box”);
- (2)绑定事件: 事件源box.事件onclick = function(){ 事件驱动程序 };
- (3)书写事件驱动程序:关于DOM的操作
常用事件如下:
绑定事件的方式
- 直接绑定匿名函数
var oDiv = document.getElementById("box");
//绑定事件的第一种方式
oDiv.onclick = function () {
alert("我是弹出的内容");
};
- 先单独定义函数,再绑定
var oDiv = document.getElementById("box");
//绑定事件的第二种方式
oDiv.onclick = fn; //注意,这里是fn,不是fn()。fn()指的是返回值。
//单独定义函数
function fn() {
alert("我是弹出的内容");
};
注意上方代码的注释。绑定的时候,是写fn,不是写fn()。fn代表的是整个函数,而fn()代表的是返回值。
- 行内绑定
<!--行内绑定-->
<div id="box" onclick="fn()"></div>
<script type="text/javascript">
function fn() {
alert("我是弹出的内容");
}
</script>
注意第一行代码,绑定时,是写的"fn()"
,不是写的"fn"
。因为绑定的这段代码不是写在js代码里的,而是被识别成了字符串。
JavaScript入口函数 window.onload()
此函数调用,是当页面加载完毕(文档和图片)的时候,触发onload()函数,文档先加载,图片资源后加载
<script type="text/javascript">
window.onload = function () {
console.log("alex"); //等页面加载完毕时,打印字符串
}
</script>
有一点我们要知道:js的加载是和html同步加载的。因此,如果使用元素在定义元素之前,容易报错。这个时候,onload事件就能派上用场了,我们可以把使用元素的代码放在onload里,就能保证这段代码是最后执行。
window.onload()方法存在的问题
- 图片加载完成才调用onload方法,大家想个问题,如果现在用户访问JD商城页面,如果JD商城中的脚本文件在window.onload()方法调用,如果此时用户网速卡了,然后图片资源加载失败了,此时用户是做不了任何操作的,所以winodw.onload()方法有很大问题。
- window.onload()方法 如果脚本中书写两个这样的方法,那么会有事件覆盖现象。
样式属性操作
所谓样式属性,就是对之前所讲解的style标签中的属性进行操作,并且通过js控制盒模型的属性(width,height等),控制盒子的显示隐藏(display:none|block),控制盒子的颜色切换(background:red|green)等等
<div class="box" style="background-color: red;"></div>
<!-- 1 盒子 初始化的时候是红色 ,点击这个盒子 切换成绿色 -->
<script type="text/javascript">
// 1.获取事件源
var oDiv = document.getElementsByClassName('box')[0];
var isRed = true;
// 2.事件 后执行的操作 异步的操作
oDiv.onclick = function(){
if (isRed) { //盒子是红色
oDiv.style.backgroundColor = 'green';
isRed = false;
}else{
oDiv.style.backgroundColor = 'red';
isRed = true;
}
};
值的操作
所谓值的操作,就是对前闭合标签和后闭合标签中间的文本内容的设置和获取。
- 双闭合标签: innerText或者innerHTML
- 单闭合标签:除了img标签,就剩input了,使用value进行赋值
<button id="btn">设置值</button>
<div id="box">
哈哈哈哈
<!--<h3>wusir</h3>-->
</div>
<input type="text" name="user" value="123" id="oinput">
<script type="text/javascript">
window.onload = function(){
// 函数 解决冗余性的代码 “僵尸代码”
/*
var oBtn = document.getElementById('btn');
var oDiv = document.getElementById('box');
var oInput = document.getElementById('oinput');
*/
function $(id){
return document.getElementById(id);
};
$('btn').onclick = function(){
// 只获取文本
// console.log($('box').innerText);
// // 对标签文本内容的设置
// $('box').innerText = 'alex';
// console.log(oDiv.innerHTML.trim());
// 获取的是所有的节点 (文本和标签 换行)
console.log($('box').innerHTML);
//
$('box').innerHTML = '<h2>alex</h2>';
//
// // 表单控件 中有value属性的 必须通过 value来设置值和赋值
console.log($('oinput').value);
$('oinput').value = '321';
}
}
标签属性操作
<a href="javascript:void(0);">
<img src="./images/image.png" alt="上一张" id="prev">
</a>
<!--
id class title src href等等
-->
<script type="text/javascript">
window.onload = function(){
// 1.获取事件源
var oImg = document.getElementById('prev');
// 2.事件 onmouseover
//鼠标悬停时
oImg.onmouseover = function(){
// console.log(oImg);
// 好比是python中self 谁调用的事件 this指的就是谁
// console.log(this);
// ./images/image.png 相对路径
console.log(this.getAttribute('src'));
console.log(this.getAttribute('id'));
console.log(this.getAttribute('alt'));
// 获取的绝对路径
console.log(this.src);
console.log(this.id);
console.log(this.alt);
// 属性的设置
// this.setAttribute('src', './images/image-hover.png');
this.src = './images/image-hover.png';
};
//鼠标移出时
oImg.onmouseout = function(){
this.setAttribute('src', './images/image.png');
}
}
节点的操作
都是函数(方法)
创建节点
格式如下:
新的标签(元素节点) = document.createElement("标签名");
比如,如果我们想创建一个li标签,或者是创建一个不存在的adbc标签,可以这样做:
<script type="text/javascript">
var a1 = document.createElement("li"); //创建一个li标签
var a2 = document.createElement("adbc"); //创建一个不存在的标签
console.log(a1);
console.log(a2);
console.log(typeof a1);
console.log(typeof a2);
</script>
结果:
插入节点
插入节点有两种方式,它们的含义是不同的。
方式1:
父节点.appendChild(新的子节点);
解释:父节点的最后插入一个新的子节点。
方式2:
父节点.insertBefore(新的子节点,作为参考的子节点);
解释:
- 在参考节点前插入一个新的节点。
- 如果参考节点为null,那么他将在父节点最后插入一个子节点。
删除节点
格式如下:
父节点.removeChild(子节点);
解释:用父节点删除子节点。必须要指定是删除哪个子节点。
如果我想删除自己这个节点,可以这么做:
node1.parentNode.removeChild(node1);
8 DOM 相关案例
1 模态框案例
需求:
打开网页时有一个普通的按钮,点击当前按钮显示一个背景图,中心并弹出一个弹出框,点击X的时候会关闭当前的模态框
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>模态框</title>
<style type="text/css">
* {
padding: 0;
margin: 0;
}
html,body{
width: 100%;
height: 100%;
}
#bg{
position: relative;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,.3);
}
#login{
width: 300px;
height: 300px;
border-radius: 3px;
background-color: #fff;
line-height: 300px;
text-align: center;
margin: 0 auto;
position: relative;
}
#close{
position: absolute;
right: 0;
top: 0;
width: 20px;
height: 20px;
background-color: red;
line-height: 20px;
text-align : center;
color: green;
cursor: pointer;
}
</style>
</head>
<body>
<button id="btn">登录</button>
<!-- 需求:
打开网页时,点击登录显示一个背景图,中心 弹出一个登录框,登录框 右上角有关闭按钮 点击关闭 关闭登录框
-->
<script type="text/javascript">
function $(id) {
return document.getElementById(id);
}
// 1.点击登录按钮 弹出登录框
// 背景
var oBg = document.createElement('div');
// 登录框
var oLogin = document.createElement('p');
// 关闭按钮
var oClose = document.createElement('span');
oBg.id = 'bg';
oLogin.id = 'login';
oClose.id = 'close';
oClose.innerText = 'X';
oLogin.innerHTML = '登录框成功弹出';
// 追加
oBg.appendChild(oLogin);
oLogin.appendChild(oClose);
console.log( $('btn'));
$('btn').onclick = function() {
alert(1);
this.parentNode.appendChild(oBg);
this.style.display =' none';
}
oClose.onclick = function(){
oBg.parentNode.removeChild(oBg);
$('btn').style.display = 'inline-block';
}
</script>
</body>
</html>
2 模拟hover选择器
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
button{
margin: 10px;
width: 100px;
height: 40px;
cursor: pointer;
}
button.active{
background-color: green;
}
</style>
</head>
<body>
<button class="active">按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
<button>按钮4</button>
<button>按钮5</button>
<script type="text/javascript">
// 需求: 鼠标悬浮 哪个button上,该button变成绿色的背景(添加类 active)
var oBtns = document.getElementsByTagName('button');
for(var i = 0; i < oBtns.length; i++){
oBtns[i].onmouseover = function(){
// 重要: 排他思想: 先把所有按钮的className设置为空,然后把(this)当前这个按钮的className设置active
for(var j = 0;j < oBtns.length; j++){
oBtns[j].className = '';
}
this.className = 'active';
}
}
for(var i = 0;i < oBtns.length; i++){
oBtns[i].onmouseout = function(){
this.className = '';
}
}
</script>
</body>
</html>
3 Tab栏选项卡
<!DOCTYPE html>
<html lang="en">
<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;
}
#tab ul li {
float: left;
width: 160px;
height: 60px;
line-height: 60px;
text-align: center;
background-color: #ccc;
}
#tab ul li a {
color: black;
display: block;
width: 100%;
height: 100%;
text-decoration: none;
}
#tab ul li.active {
background-color: red;
}
#tab p {
display: none;
height: 200px;
text-align: center;
line-height: 200px;
background-color: red;
}
#tab p.active {
display: block;
}
</style>
</head>
<body>
<div id="tab">
<ul>
<li class="active">
<a href="javascript:void(0);">首页</a>
</li>
<li>
<a href="javascript:void(0);">新闻</a>
</li>
<li>
<a href="javascript:void(0);">图片</a>
</li>
</ul>
<p class="active">首页内容</p>
<p>新闻内容</p>
<p>图片</p>
</div>
<script type="text/javascript">
// 需求: 鼠标放在上面,li上 li本身变色(添加类) 对应下面p也显示出来(添加类)
// 思路: 1.点亮上面的盒子 2 利用索引值来显示下面的盒子
/*
// 变量提升
var a;
console.log(a);//undefined
a = 10;
console.log(a);
*/
var tabLi = document.getElementsByTagName('li');
var tabP = document.getElementsByTagName('p');
for(var i = 0; i < tabLi.length; i++){
// 将 i保存到 li标签对象中
tabLi[i].index = i;
// for循环和点击事件 谁快 i 全局作用域(块级作用域) 3
tabLi[i].onclick = function(){
for(var j = 0;j < tabLi.length;j++){
tabLi[j].className = '';
tabP[j].className = '';
}
this.className = 'active';
// Cannot set property 'className' of undefined
console.log(i);
tabP[this.index].className = 'active';
}
}
</script>
</body>
</html>