今日学习任务
[ ] 1.DOM节点
[ ] a.了解节点与元素的区别
[ ] b.节点与元素相关操作(常用只有两个:子元素children与父节点parentNode)
[ ] 子节点与子元素
- 兄弟节点与兄弟元素
- 第一个子节点与第一个子元素
- 最后一个子节点与最后一个子元素
- 获取父节点
- 案例:点击关闭二维码
[ ] 2.dom增删改页面元素
[ ] a.语法
[ ] 创建子元素createElement()
- 增加子元素appendChild()
- 插入子元素insertBefore()
- 替换子元素replaceChild()
- 移除子元素removeChild()
- 克隆元素cloneNode()
[ ] b.案例
[ ] 选择职业技能
- 模拟百度搜索框
[ ] 3.BOM:浏览器对象模型
[x] window对象:浏览器窗口
- location对象:地址栏
- history对象:网页历史记录
- navigator对象:浏览器信息
- screen对象:电脑屏幕信息
01-DOM节点:网页一切内容皆节点
1.1-DOM节点介绍
- 1.什么是节点:在HTML文档中,一切皆节点(HTML文档本身、标签、属性、注释内容、文本)
- 2.什么是元素:元素在HTML中叫做标签,在JS的dom对象中称为元素(可以理解为标签的面向对象的叫法)
- 3.HTML标签属于节点的一种,叫做元素节点
4.节点三要素:
- 节点类型:标签、属性、注释、文本,nodeType
- 节点名称:p、div、class(属性名),nodeName
- 节点的值:one(属性的值),nodeValue
在JavaScript中,document这个对象大家一定很熟悉,哪怕是刚刚开始学习的新人,也会很快接触到这个对象。而document对象不仅仅是一个普通的JavaScript内置对象,它还是一个巨大API的核心对象,这个巨大的API就是DOM(Document Object Model),它将文档的内容呈现在JS面前,并赋予了JS操作文档的能力。
- DOM树体现着HTML页面的层级结构,学习中经常提到的父元素子元素的说法也是建立在树这种数据结构的基础之上的,而DOM文档树则包含文档中所有内容。
- HTML页面中的所有内容都会体现在DOM文档树中,要理解这种结构,对构成它的每个节点就要先有了解。下面是DOM节点的基本类别,以及各自类别基本属性的值及简单介绍:
1.2-元素节点与属性节点
1.元素节点
- 类型 nodeTypoe:1
- 名称 nodeName:标签名大写
- 值 nodeValue : null
2.属性节点
- 类型 nodeTypoe:2
- 名称 nodeName:属性名
- 值 nodeValue : 属性值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div class="one" id="box">我是一个div</div>
<p class="one" id="p1">我是一个p</p>
</body>
<script>
/*1.元素节点
* 类型 nodeTypoe:1
* 名称 nodeName:标签名大写
* 值 nodeValue : null
2.属性节点
* 类型 nodeTypoe:2
* 名称 nodeName:属性名
* 值 nodeValue : 属性值
*/
//1.获取到元素节点
let box = document.querySelector('#box');
let p1 = document.querySelector('#p1');
//2.查看元素节点
console.log ( box.nodeType );//1
console.log ( box.nodeName );//DIV
console.log ( box.nodeValue );//null
console.log ( p1.nodeType );//1
console.log ( p1.nodeName );//P
console.log ( p1.nodeValue );//null
//3.获取到属性节点
console.log ( box.getAttribute ( "class" ) );//这个只是单纯的获取class属性的值,不是获取属性节点
console.log ( box.attributes );//查看box元素的所有属性节点
//4.查看属性节点
console.log ( box.attributes[0].nodeType );//2
console.log ( box.attributes[0].nodeName );//class
console.log ( box.attributes[0].nodeValue );//one
</script>
</html>
1.3-文本节点与注释节点与文档节点
1.文本节点
- 类型 nodeTypoe:3
- 名称 nodeName:#text
- 值 nodeValue : 文本内容
2.注释节点
- 类型 nodeTypoe:8
- 名称 nodeName:#comment
- 值 nodeValue : 注释内容
3.文档节点
- 类型 nodeTypoe:9
- 名称 nodeName:#document
- 值 nodeValue : null
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<ul id="ul1">我是文本内容
<!--我是注释内容-->
<li>隔壁老王1</li>
<li>隔壁老王2</li>
<li>隔壁老王3</li>
<li>隔壁老王4</li>
<li>隔壁老王5</li>
</ul>
</body>
<script>
/*1.文本节点
* 类型 nodeTypoe:3
* 名称 nodeName:#text
* 值 nodeValue : 文本内容
*
2.注释节点
* 类型 nodeTypoe:8
* 名称 nodeName:#comment
* 值 nodeValue : 注释内容
*
3.文档节点
* 类型 nodeTypoe:9
* 名称 nodeName:#document
* 值 nodeValue : null
*/
//获取元素节点
let ul1 = document.querySelector('#ul1');
//获取元素节点下的所有子节点(元素之间的空格部分可以看作一个没有内容的文本节点)
let nodeList = ul1.childNodes;
console.log ( nodeList );
//查看文本节点
console.log ( nodeList[ 0 ].nodeType );//3
console.log ( nodeList[ 0 ].nodeName );//#text
console.log ( nodeList[ 0 ].nodeValue );//文本内容
//查看注释节点
console.log ( nodeList[ 1 ].nodeType );//8
console.log ( nodeList[ 1 ].nodeName );//#comment
console.log ( nodeList[ 1 ].nodeValue );//注释内容
//查看文档节点(文档节点就是document自己)
console.log ( document.nodeType );//9
console.log ( document.nodeName );//#document
console.log ( document.nodeValue );//null
</script>
</html>
1.4-获取子节点与子元素
childNodes:获取子节点:(文本节点,注释节点,子元素节点)
- 细节:属性节点通过attribute来获取,一般用的不多
- 浏览器兼容问题:IE8及之前不包含非空文本
children:获取子元素:(元素节点)
- 浏览器兼容问题: IE8及之前包含注释节点
<!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>
<ul id="ul1">
我是班长的小迷妹
<!-- 我是暗恋班长的班花 -->
<li>我是班长1</li>
<li>我是班长2</li>
<li>我是班长3</li>
<li>我是班长4</li>
<li>我是班长5</li>
</ul>
<script>
/*本小节知识点:获取子元素与子节点
1.获取子元素: 父元素.children
2.获取子节点: 父元素.childNodes
*/
let ul1 = document.querySelector('#ul1');
//1.获取子元素: 元素节点
/*
谷歌火狐:元素节点
IE8:包含注释和元素
*/
console.log(ul1.children);
//2.获取子节点: 元素节点 文本节点 注释节点
/*
谷歌火狐: 包含空文本
IE8: 不包含空文本
*/
console.log(ul1.childNodes);
</script>
</body>
</html>
1.5-兄弟节点与兄弟元素
本小节知识点:获取兄弟节点与兄弟元素
nextSibling:获取下一个节点 previousSibling:获取上一个节点
- IE8及之前:文本(不包含非空)、注释、元素
- 其他浏览器:文本(包含非空)、注释、元素
<!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>
<ul id="ul1">
我是班长的小迷妹
<!-- 我是暗恋班长的班花 -->
<li>我是班长1</li>
<!-- svkhskvhb -->
<li id="li2">我是班长2</li>666
<li>我是班长3</li>
<li>我是班长4</li>
<li>我是班长5</li>
</ul>
<script>
/*本小节知识点:获取兄弟元素与兄弟节点
1.获取兄弟节点
* 上一个节点: 元素.previousSibling
* 下一个节点: 元素.nextSibling
2.获取兄弟元素(常用)
* 上一个元素:元素.previousElementSibling
* 下一个元素 元素.nextElementSibling
*/
let ul1 = document.querySelector('#ul1');
let li2 = document.querySelector('#li2');//班长2
//1.兄弟节点: 元素、注释、文本
//1.1 获取上一个节点
console.log(li2.previousSibling);
//1.2 获取下一个节点
console.log(li2.nextSibling);
//2.兄弟元素: 元素
//2.1 获取上一个元素
console.log(li2.previousElementSibling);
//2.2 获取下一个元素
console.log(li2.nextElementSibling);
</script>
</body>
</html>
1.6-第一个子节点与第一个子元素
- 1.firstChild : 第一个子节点
2.firstElementChild:第一个子元素节点
- 他们两者的浏览器兼容问题与兄弟节点一致
<!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>
<ul id="ul1">
我是班长的小迷妹
<!-- 我是暗恋班长的班花 -->
<li>我是班长1</li>
<!-- svkhskvhb -->
<li id="li2">我是班长2</li>666
<li>我是班长3</li>
<li>我是班长4</li>
<li>我是班长5</li>
</ul>
<script>
/*本小节知识点:获取第一个子元素与第一个子节点
1.获取第一个子节点: 父元素.firstChild
2.获取第一个子元素: 父元素.firstElementChild
*/
let ul1 = document.querySelector('#ul1');
//1.获取第一个子节点 (元素 文本 注释)
console.log(ul1.firstChild);
//2.获取第一个子元素: 元素
console.log(ul1.firstElementChild);
</script>
</body>
</html>
1.7-最后一个节点与最后一个元素
- 1.lastChild : 最后一个子节点
2.lastElementChild:最后一个子元素节点
- 他们两者的浏览器兼容问题与兄弟节点一致
<!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>
<ul id="ul1">
我是班长的小迷妹
<li>我是班长1</li>
<!-- svkhskvhb -->
<li id="li2">我是班长2</li>666
<li>我是班长3</li>
<li>我是班长4</li>
<li>我是班长5</li>
<!-- 我是暗恋班长的班花 -->
</ul>
<script>
/*本小节知识点:获取最后一个子元素与最后一个子节点
1.获取最后一个子节点: 父元素.lastChild
2.获取最后一个子元素: 父元素.lastElementChild
*/
let ul1 = document.querySelector('#ul1');
//1.获取最后一个子节点 (元素 文本 注释)
console.log(ul1.lastChild);
//2.获取最后一个子元素: 元素
console.log(ul1.lastElementChild);
</script>
</body>
</html>
1.8-获取父节点
parentNode:获取元素的父元素节点
- 细节:一个元素的父节点一定是一个元素,而不是(文本、注释、属性),只有元素才有子节点
<!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>
<ul id="ul1">
我是班长的小迷妹
<li>我是班长1</li>
<!-- svkhskvhb -->
<li id="li2">我是班长2</li>666
<li>我是班长3</li>
<li>我是班长4</li>
<li>我是班长5</li>
<!-- 我是暗恋班长的班花 -->
</ul>
<script>
//获取元素的父节点: 子元素.parentNode
let li2 = document.getElementById('li2');
//获取元素的父节点一定是元素。 (因为只有元素节点才会有节点)
console.log(li2.parentNode);//ul1
console.log(li2.parentNode.parentNode);//body
console.log(li2.parentNode.parentNode.parentNode);//html
console.log(li2.parentNode.parentNode.parentNode.parentNode);//document
console.log(li2.parentNode.parentNode.parentNode.parentNode.parentNode);//null
</script>
</body>
</html>
1.9-案例:点击关闭二维码
- 需求:点击二维码图片右上角的小叉叉,关闭二维码
- 思路:给子元素添加一个点击事件,点击之后移除父元素
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>关闭二维码</title>
<style>
.box {
border: 1px solid #D9D9D9;
margin: 100px auto;
position: relative;
width: 107px;
}
#x {
border: 1px solid #D9D9D9;
width: 14px;
height: 14px;
line-height: 14px;
color: #D6D6D6;
cursor: pointer;
position: absolute;
top: 0;
left: -15px;
}
</style>
</head>
<body>
<div class="box">
<img src="images/taobao.jpg" alt="" />
<span id="x">×</span>
</div>
<script>
//1.获取元素
let xx = document.querySelector('#x');
//2.注册事件
xx.onclick = function () {
//3.事件处理:隐藏box
// box1.style.display = 'none';
//点击xx,就把xx的父元素给隐藏
this.parentNode.style.display = 'none';
};
</script>
</body>
</html>
02-dom增删改页面元素
语法 | 示例 | 描述 |
---|---|---|
document.createElement() | document.createElement(‘li’) | 创建空标签元素 |
父元素.appendChild(子元素) | ul.appendChild(li) | 添加子元素 |
父元素.insertBefore(子元素) | ul.insertBefore(元素A,元素B) | 将元素A插入到元素B的前面 |
父元素.replaceChild(子元素) | ul.replaceChild(元素A,元素B) | 元素A替换元素B |
父元素.removeChild(子元素) | ul.removeChild(li) | 移除子元素 |
1.1-创建元素三种方式介绍
1.document.write():慎用,可能会覆盖原本内容
- 解析字符串识别标签
2.innerHTML:创建元素过多时(100以内可以忽略),会损耗性能
- 解析字符串识别标签
- 直接赋值 元素.innerHTML 会替换原本内容,如果不想替换使用 += 拼接
3.document.createElement():dom推荐方式
- 动态创建一个dom对象(空标签,需要自己设置属性)在内存中
- 需要使用appendChild来添加到HTML
document.write():慎用,因为可能会覆盖原本的内容
- 覆盖内容的原理了解即可:编译器从上往下解析HTML的时候会形成一个文档流,这个文档流会在文档所有的HTML标签解析后关闭。不会覆盖的情况:如果在关闭这个文档流之前调用document.write(),则不会覆盖会覆盖的情况:如果在关闭文档流之后调用document.write(),会开启一个新的文档流,此时会把上一个文档流中的内容覆盖
<!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>我是班长</div>
<button onclick="document.write('<p>我是马云6666</p>');">点我有惊喜</button>
<script>
//1.document.write()
//不常用,因为可能会覆盖网页原先的内容
/*覆盖原理
1.当html文件加载的时候,浏览器会生成一个默认文档流,当页面全部加载完毕之后默认文档流会完毕。
如果此时调用 document.write()浏览器会生成一个新的文档流,重新渲染页面
2.不会覆盖: 在默认文档流没有关闭之前调用 document.write()
3.会覆盖: 在默认文档流关闭之后调用 document.write()
*/
document.write('<p>我是马云</p>');
//2.innerHTML : 少用,存在性能问题(100以内忽略不计)
//直接赋值会替换原有的内容
// document.body.innerHTML = '<div>黑马程序员</div><a href="#">我是链接</a>';
//如果希望添加,可以使用字符串连接符
// document.body.innerHTML += '<div>黑马程序员</div><a href="#">我是链接</a>';
//3. dom推荐方式: createElement
/*
参数:标签名字符串
返回值:元素节点
特点: (1)创建出来的元素只是在内存中,并没有显示到页面中,需要手动添加
(2)创建出来的是空标签
*/
// (1) 创建空元素
// let box = document.createElement('div');
// (2) 添加属性
// box.id = 'box';
// box.innerText = '我是新来的div';
// (3) 添加到页面
// document.body.appendChild(box);
</script>
</body>
</html>
1.2-练习:点击按钮创建多个标签
<!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>
<button id="btn">点我</button>
<script>
//注册事件
document.querySelector('#btn').onclick = function(){
//1.innerHTML:1340.5ms
// console.time()
// for(let i = 1;i<=1000;i++){
// document.body.innerHTML += '<p>我是第' + i + '个p标签</p>'
// };
// console.timeEnd()
//2.createElement : 2ms
console.time()
for(let i = 1;i<=1000;i++){
//1.创建空标签 (1)空标签 (2)只是在内存创建,需要手动添加
let p = document.createElement('p');
//2.添加属性
p.innerText = '我是第' + i + '个p标签';
//3.添加到页面: appendChild()
document.body.appendChild(p);
};
console.timeEnd()
}
</script>
</body>
</html>
1.3-添加子元素:appendChild()
appendChild()添加元素有三种情况
- (1)如果是一个新的子元素,则默认会添加到最后
- (2)如果是一个已存在的子元素,相当于移动到最后面
- (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>
<ul id="ul1">
<li>隔壁老牛1</li>
<li>隔壁老牛2</li>
<li>隔壁老牛3</li>
<li>隔壁老牛4</li>
<li>隔壁老牛5</li>
</ul>
<ul id="ul2">
<li>我是马云1</li>
<li id="li2">我是马云2</li>
<li>我是马云3</li>
<li>我是马云4</li>
<li>我是马云5</li>
</ul>
<script>
/*本小节知识点: 父元素.appendChild(子元素)
1. 新创建子元素 : 添加到最后面
2. 已经存在元素 : 移动到最后面
3. 父元素有子元素: 父元素和子元素一起移动到后面
*/
let ul1 = document.getElementById('ul1');
let ul2 = document.getElementById('ul2');
//1.新创建元素
let newLi = document.createElement('li');
// newLi.innerText = '我是新来的';
ul1.appendChild(newLi);
//2.已经存在的元素
let li2 = document.getElementById('li2');//马云2
ul1.appendChild(li2);
//3.元素有子元素
ul1.appendChild(ul2);
</script>
</body>
</html>
1.4-插入子元素:inertBefore()
insertBefore:插入子元素到指定位置
- 语法:
父元素.insertBefore(要插入的标签,插入到哪一个标签前面)
特点:与appendChildNode一致
- (1)如果是新元素则插入到指定位置
- (2)如果是已存在元素则移动到指定位置
- (3)如果元素有子元素,则子元素随着它一起移动
- 如果想插入到某元素后面,没有直接的api,可以先获取该元素的下一个元素,然后插入到下一个元素前面即可
<!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>
<ul id="ul1">
<li>隔壁老牛1</li>
<li>隔壁老牛2</li>
<li id="li3">隔壁老牛3</li>
<li>隔壁老牛4</li>
<li>隔壁老牛5</li>
</ul>
<ul id="ul2">
<li>我是马云1</li>
<li id="li2">我是马云2</li>
<li>我是马云3</li>
<li>我是马云4</li>
<li>我是马云5</li>
</ul>
<script>
/*本小节知识点: 父元素.insertBefore(A元素,B元素) : A元素插入B元素的前面
1. 新创建子元素 : 添加到指定位置
2. 已经存在元素 : 移动到指定位置
3. 父元素有子元素: 元素和子元素一起移动到指定位置
*/
let ul1 = document.getElementById('ul1');
let ul2 = document.getElementById('ul2');
let li3 = document.getElementById('li3');//老牛3
//1.新创建元素
let newLi = document.createElement('li');
newLi.innerText = '我是新来的';
ul1.insertBefore(newLi,li3);//newLi插入到li3的前面
//2.已经存在的元素
let li2 = document.getElementById('li2');//马云2
ul1.insertBefore(li2,li3);
//3.元素有子元素
ul1.insertBefore(ul2,li3);
</script>
</body>
</html>
1.5-替换子元素:replaceChild()
- 替换子元素:replaceChild() 语法:
父元素.replaceChile(新元素,旧元素)
特点:
- 1.如果是新创建的元素,则直接替换
- 2.如果是已存在的元素(不论这个元素是自己的子元素还是别人的)会将新元素移动到旧元素位置,并且旧元素被移除
- 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>
<ul id="ul1">
<li>隔壁老牛1</li>
<li>隔壁老牛2</li>
<li id="li3">隔壁老牛3</li>
<li>隔壁老牛4</li>
<li>隔壁老牛5</li>
</ul>
<ul id="ul2">
<li>我是马云1</li>
<li id="li2">我是马云2</li>
<li>我是马云3</li>
<li>我是马云4</li>
<li>我是马云5</li>
</ul>
<script>
/*本小节知识点: 父元素.replaceChild(A元素,B元素) A元素替换B元素
1. 新创建子元素 : 替换元素
2. 已经存在元素 : 先移动,后替换
3. 父元素有子元素: 父元素和子元素一起 先移动,后替换
*/
let ul1 = document.getElementById('ul1');
let ul2 = document.getElementById('ul2');
let li3 = document.getElementById('li3');//老牛3
//1.新创建元素
// let newLi = document.createElement('li');
// newLi.innerText = '我是新来的';
// ul1.replaceChild(newLi,li3);//newLi替换li3
//2.已经存在的元素
// let li2 = document.getElementById('li2');//马云2
// ul1.replaceChild(li2,li3);//li2替换li3
//3.元素有子元素
ul1.replaceChild(ul2,li3);//ul2ti换li3
</script>
</body>
</html>
1.6-移除子元素:removeChild()
removeChild:移除子元素 语法:
父元素.removeChild(子元素)
- 1.不能自己移除自己(只能让爸爸干掉自己)
- 2.父元素只能移除自己的子元素,不能移除别人的子元素(只有亲爸爸才能干掉自己)
<!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>
<ul id="ul1">
<li>隔壁老牛1</li>
<li>隔壁老牛2</li>
<li id="li3">隔壁老牛3</li>
<li>隔壁老牛4</li>
<li>隔壁老牛5</li>
</ul>
<ul id="ul2">
<li>我是马云1</li>
<li id="li2">我是马云2</li>
<li>我是马云3</li>
<li>我是马云4</li>
<li>我是马云5</li>
</ul>
<script>
/*本小节知识点: 父元素.removeChild(子元素)
1. 父元素只能移除自己的子元素
2. 父元素不能移除别人的子元素
3. 元素不能自己移除自己的
*/
let ul1 = document.getElementById('ul1');
let ul2 = document.getElementById('ul2');
let li3 = document.getElementById('li3');//老牛3
let li2 = document.getElementById('li2');//马云2
//1.元素自己不能移除自己(不能自杀)
// li3.removeChild(li3);
//2.父元素不能移除别人的子元素(不能杀别人的儿子)
// ul1.removeChild(li2);
//3.父元素只能移除自己的子元素
ul2.removeChild(li2);
</script>
</body>
</html>
1.7-克隆元素:cloneNode():自主学习
cloneNode:克隆元素 语法:
元素.cloneNode(布尔)
false:默认,浅克隆
true:深克隆
- 1.克隆目标元素
2.可能分为两种
- 浅克隆:只克隆元素本身,不包含子节点(文本、元素)
- 深克隆:克隆元素本身以及其子节点(文本、元素)
03-dom综合案例(尝试练习)
1.1-案例:选择职业技能
需求分析:
- 点击 >> :将左边所有的内容移动到右边
- 点击 << :将右边所有的内容移动到左边
- 点击 > :将左边选中的内容移动到右边
- 点击 < :将右边选中的内容移动到左边
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
select {
width: 100px;
height: 150px;
}
</style>
</head>
<body>
<select name="" id="left" multiple>
<option value="">web工程师</option>
<option value="">android工程师</option>
<option value="">ios工程师</option>
<option value="">php工程师</option>
<option value="">nodejs工程师</option>
<option value="">pyton小白</option>
<option value="">足疗爱好者</option>
</select>
<button id="btn1">>></button>
<button id="btn2"><<</button>
<button id="btn3">></button>
<button id="btn4"><</button>
<select name="" id="right" multiple></select>
<script>
/*
1.分析需求(交互):
(1)全部右移:将左边left的children移动到右边right
(2)全部左移: 将右边right的children移动到左边left
(3)选中右移: 将左边left的选中的children移动到右边right
(4)选中坐移:将右边right选中的children移动到左边left
2.思路分析(事件三要素)
获取元素:事件源:
注册事件:事件类型
事件处理:
*/
//1.获取元素
let left = document.querySelector('#left');
// console.log(left.children);
let right = document.querySelector('#right');
let btn1 = document.querySelector('#btn1');//全部右移
let btn2 = document.querySelector('#btn2');//全部左移
let btn3 = document.querySelector('#btn3');//选中右移
let btn4 = document.querySelector('#btn4');//选中左移
//2.注册事件
//(2.1)全部右移:将左边left的children移动到右边right
btn1.onclick = function () {
/*
1.发现问题:左边的所有子元素无法全部添加到右边
2.分析原因:当数组的元素发生移动的时候,后面所有的元素下标就会前移
3.解决问题: 只要元素移动,由于下标已经前移,所以循环变量i不能自增
*/
//3.事件处理
for(let i = 0;i<left.children.length;i++){
right.appendChild(left.children[i]);
i--;//抵消本次循环变量自增
};
};
//(2.2)全部左移: 将右边right的children移动到左边left
btn2.onclick = function () {
for(let i = 0;i<right.children.length;i++){
left.appendChild(right.children[i]);
i--;//抵消本次循环变量自增
};
};
//(2.3)选中右移: 将左边left的选中的children移动到右边right
btn3.onclick = function () {
for(let i = 0;i<left.children.length;i++){
console.log(left.children[i].selected);
//如果选中状态是select则移动
if(left.children[i].selected){
right.appendChild(left.children[i]);
//只有元素发生移动,下标才会前移,才需要i--
i--;//抵消本次循环变量自增
};
};
};
//(2.4)选中坐移:将右边right选中的children移动到左边left
btn4.onclick = function () {
for(let i = 0;i<right.children.length;i++){
//如果选中状态是select则移动
if(right.children[i].selected){
left.appendChild(right.children[i]);
//只有元素发生移动,下标才会前移,才需要i--
i--;//抵消本次循环变量自增
};
};
};
</script>
</body>
</html>
1.2-案例:模拟百度搜索框
需求分析:
1.键盘松开txt : 根据搜索内容显示对应搜索列表ul
2.鼠标移入li元素:颜色变红
3.鼠标移出li元素:颜色变原先颜色
4.鼠标点击li元素: (1)搜索框显示点击的li元素文本 (2)情况内容列表ul
思路分析:事件三要素
1 获取元素:
2 注册事件:
3 事件处理:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
* {
margin: 0;
padding: 0;
}
body {
font-size: 20px;
}
.box {
width: 600px;
height: 40px;
margin: 200px auto;
position: relative;
}
#txt {
width: 498px;
height: 38px;
border: 1px solid #ccc;
font-size: 20px;
}
#search {
width: 100px;
height: 40px;
}
#keywords {
position: absolute;
top: 40px;
left: 0;
background-color: rgb(12, 255, 24);
list-style: none;
width: 500px;;
}
li {
line-height: 24px;
}
</style>
</head>
<body>
<div class="box">
<div class="top">
<input type="text" id="txt"/><input type="button" value="search" id="search"/>
</div>
<ul id="keywords"></ul>
</div>
<script src="common.js"></script>
<script>
/* 需求分析:
1.键盘松开txt : 根据搜索内容显示对应搜索列表ul
2.鼠标移入li元素:颜色变红
3.鼠标移出li元素:颜色变原先颜色
4.鼠标点击li元素: (1)搜索框显示点击的li元素文本 (2)情况内容列表ul
思路分析:事件三要素
1 获取元素:
2 注册事件:
3 事件处理:
*/
let keywords = ["小马哥", "小马哥为什么喜欢挖坑", "小马哥有老婆吗", "小马哥是谁", "广东人", "广东人爱吃", "广东人爱吃什么","广东人什么都吃","华为","华为任正非","华为余大嘴","华为被美国封杀","新八国联军封杀中国华为","中国抗议胜利","全世界都在看中国","中国出手了","黑马.中国","Java","王思聪","王健林","社会王","隔壁老王"];
//1. 获取元素:
let txt = document.getElementById('txt');
let ul = document.getElementById('keywords');
//2.注册事件:
//2.1 键盘松开
txt.onkeyup = function ( ) {
//3.事件处理 : 根据搜索内容显示对应文本
//3.1 获取搜索文本
let search = this.value;
//3.2 每一次输入之前应该把之前的内容清空,以本次输入为准
ul.innerHTML = '';
//3.3 如果用户没有输入,则不搜索
if(search.length == 0){
return;
};
console.log ( search );
//3.3 根据搜索文本显示对应内容
searchTxt(search);
};
/**
*
* @param searchTxt 要搜索的文本
*/
function searchTxt ( searchTxt ) {
//将数组中的内容显示到页面
for(let i = 0;i<keywords.length;i++){
let str = keywords[i];
//如果搜索文本searchTxt在str中则显示
if (str.indexOf(searchTxt) != -1){
//1.创建空li元素
let li = document.createElement('li');
//2.设置文本
li.innerText = str;
//3.li元素添加到ul
ul.appendChild(li);
//每一个创建的li元素都有三个事件
//鼠标移入:颜色变红
li.onmouseover = function ( ) {
//(1)先用一个自定义属性存储原先的颜色
this.aaa = this.style.backgroundColor;
//(2)修改颜色为红色
this.style.backgroundColor = 'red';
};
//鼠标移出:颜色恢复原先的颜色
li.onmouseout = function ( ) {
this.style.backgroundColor = this.aaa;
};
//鼠标单击:
li.onclick = function ( ) {
//(1)搜索框文本变成单击的li元素文本
txt.value = this.innerText;
//(2)清空内容列表
ul.innerHTML = '';
// for(let i = 0;i<ul.children.length;i++){
// ul.removeChild(ul.children[i]);
// }
};
}
}
};
</script>
</body>
</html>
1.3-案例:综合表格处理
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
.main,
table {
width: 800px;
margin: 0 auto;
}
.main {
height: 40px;
line-height: 40px;
}
table,
th,
td {
border: 1px solid black;
border-collapse: collapse;
}
.optd {
width: 200px;
}
.addTable {
width: 780px;
padding: 10px;
border: 1px solid green;
/* 固定位置 */
position: fixed;
top: 200px;
left: 50%;
margin-left: -400px;
/* 标准流 */
/* margin: 0 auto; */
background-color: #fff;
display: none;
}
.addTable table {
width: 100%;
text-align: center;
margin-bottom: 10px;
}
</style>
</head>
<body>
<div class="main">
<input type="button" value="新增一行" id="add" />
</div>
<table id="table">
</table>
<!--用于新增表格获取数据的模块-->
<div class="addTable" id="addRow">
<table>
<tr>
<th>学号</th>
<th>姓名</th>
<th>性别</th>
<th>年龄</th>
</tr>
<tr>
<td><input type="text" id="number" /></td>
<td><input type="text" id="name" /></td>
<td>
<select id="gender">
<option>男</option>
<option>女</option>
</select>
</td>
<td><input type="text" id="age" /></td>
</tr>
</table>
<div>
<input type="button" value="确定" id="sure" />
<input type="button" value="取消" id="cancle" />
</div>
</div>
<script>
/*思路分析
1.根据json数据生成页面结构
1.1-动态创建表头
1.2-根据json对象动态创建tr
1.3-动态创建tr中的三个操作按钮
函数封装:
a.将创建tr封装到函数中:因为新增一行也会用到
b.将根据id获取元素封装到函数中:因为页面多个地方会用到
2.注册页面事件
2.1-点击新增一行
2.2-新增确定
2.3-新增取消
2.4-向上移动
2.5-向下移动
2.6-删除
3.处理事件
*/
let head = ["学号", "姓名", "性别", "年龄", "操作"];
let data = [
{ "number": "001", "name": "李狗蛋", "gender": "男", "age": 16 },
{ "number": "002", "name": "王大柱", "gender": "女", "age": 17 },
{ "number": "003", "name": "李葫芦", "gender": "男", "age": 15 },
{ "number": "004", "name": "小明", "gender": "男", "age": 18 },
{ "number": "005", "name": "小红", "gender": "女", "age": 16 }
];
//1.根据数组内容:生成tableb表格结构
let table = document.querySelector('#table');
//1.1 生成表头
//(1)创建空标签
let headTr = document.createElement('tr');
//(2)设置内容
for (let i = 0; i < head.length; i++) {
//1.创建空标签
let th = document.createElement('th');
//2.设置内容
th.innerText = head[i];
//3.添加到页面
headTr.appendChild(th);
};
//(3)添加到页面
table.appendChild(headTr);
//1.2 生成表格内容
for (let i = 0; i < data.length; i++) {
let obj = data[i];
console.log(obj);
createRow(obj);
};
function createRow(obj) {
//(1)创建空标签
let tr = document.createElement('tr');
//(2)设置内容 : 遍历对象的属性,生成td
for (let key in obj) {
console.log(obj[key]);
//1.创建空td
let td = document.createElement('td');
//2.设置内容
td.innerText = obj[key];
//3.添加到tr
tr.appendChild(td);
};
//(3)最后一个td里面有三个按钮
let buttonTd = document.createElement('td');
//(3.1)创建元素 :createElement 三行
let buttonUp = document.createElement('button');
//(3.2)设置内容
buttonUp.innerText = '向上移动';
buttonUp.onclick = moveUp;
buttonTd.appendChild(buttonUp);
let buttonDown = document.createElement('button');
buttonDown.innerText = '向下移动';
buttonDown.onclick = moveDown;
buttonTd.appendChild(buttonDown);
let buttonDelete = document.createElement('button');
buttonDelete.innerText = '删除';
buttonDelete.onclick = moveDelete;
buttonTd.appendChild(buttonDelete);
tr.appendChild(buttonTd);
//(3)添加到table
table.appendChild(tr);
}
//2.1 点击新增一行 add : 显示addRow
let add = document.getElementById('add');
let addRow = document.getElementById('addRow');
add.onclick = function () {
addRow.style.display = 'block';
};
//2.2 取消 : 隐藏addRow
let cancle = document.getElementById('cancle');
cancle.onclick = function () {
addRow.style.display = 'none';
};
//2.3 确定: sure
let sure = document.getElementById('sure');
sure.onclick = function () {
//3.1 获取输入数据
let obj = {};
obj.number = document.getElementById('number').value;
obj.name = document.getElementById('name').value;
obj.gender = document.getElementById('gender').children[0].selected ? '男' : '女';
obj.age = document.getElementById('age').value;
console.log(obj);
//3.2 将数据添加到表格
createRow(obj);
//3.3 隐藏addRow
addRow.style.display = 'none';
};
//向上移动
function moveUp() {
console.log(this);//button
console.log(this.parentNode);//td
console.log(this.parentNode.parentNode);//tr
//需求: 爷爷插入到 爷爷的哥哥的前面
if (this.parentNode.parentNode == table.children[1]) {// 下标0是表头,内容从下标1开始
alert('不能移动');
} else {
let yeye = this.parentNode.parentNode;
let yeGe = this.parentNode.parentNode.previousElementSibling;
table.insertBefore(yeye, yeGe);
}
};
//向下移动
function moveDown() {
if (this.parentNode.parentNode == table.lastElementChild) {
alert('已经是最后一个');
} else {
let yeye = this.parentNode.parentNode;
let yeDiDi = this.parentNode.parentNode.nextElementSibling.nextElementSibling;
table.insertBefore(yeye, yeDiDi);
}
};
//删除
function moveDelete() {
if (confirm('你确定要移除我的爷爷吗?')) {
table.removeChild(this.parentNode.parentNode);
};
};
</script>
</body>
</html>
04-BOM浏览器对象模型
1.1-BOM与DOM介绍
JavaScript语言由三部分组成
ECMAJavaScript:定义了js的语法规范
Dom:document object model文档对象模型:一个HTML文档中所有的一切都是dom对象
* Dom定义了一套操作HTML文档的API(节点的增删改查)
- Bom:Browser object model浏览器对象模型 例如:一个浏览器的窗口就是一个window对象
* Bom定义了一套操作浏览器窗口的API
Bom主要由五大对象组成:
- window:浏览器核心对象
- location:包含当前页面的URL信息
- history:history对象主要用于记录你当前窗口的历史记录
- navigator:包含当前浏览器的信息,例如用的什么浏览器,操作系统版本等
screen:获取用户电脑的屏幕分辨率
- 这个一般不用,因为对开发者没啥作用
1.2-window对象
1.window对象:指的是当前浏览器窗口,它是JS中的顶级对象
(1).所有的全局变量(var声明的)都是window对象的属性:最顶级的对象
- document对象
- bom对象
- 全局的方法:alert(),setInterval()………..
(2).只要是window的属性和方法,在使用的时候都可以省略window
- 例如:window.alert() 可以省略window写成alert()
- 例如:window.document 可以省略window写成document
(3).window对象有一个特殊属性叫做name
- 它永远都是一个字符串,无论给他赋什么值
2.window对象有两个常用的方法:open()与close()
- open():打开一个窗口
- close():关闭一个窗口
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<input type="button" value="点我打开一个新窗口" id="open">
<input type="button" value="点我有惊喜" id="close">
</body>
<script>
/*1.window对象:指的是当前浏览器窗口,它是JS中的顶级对象
* (1).所有的全局变量都是window对象的属性:最顶级的对象
* document对象
* bom对象
* 全局的方法:alert(),setInterval()...........
* (2).只要是window的属性和方法,在使用的时候都可以省略window
* 例如:window.alert() 可以省略window写成alert()
* 例如:window.document 可以省略window写成document
* (3).window对象有一个特殊属性叫做name
* 它永远都是一个字符串,无论给他赋什么值
*
2.window对象有两个常用的方法:open()与close()
* open():打开一个窗口
* close():关闭一个窗口
*/
//1.window是顶级对象,所有的全局变量都是window对象的属性
let age = 18;
console.log ( window.age );
//2.只要是window对象的属性和方法,window可以省略
console.log ( window.document === document );true
//3.window有一个特殊的属性叫做name,它永远都是一个字符串
console.log ( window.name );//默认是一个空字符串
window.name = 123456;
console.log ( name );//永远都是一个字符串
//就算你重新声明一个变量叫做name,也无法覆盖它
let name = [123];
console.log ( name );
//打开新窗口
document.getElementById('open').onclick = function ( ) {
/**
* @param 第一个参数:URL 要打开的窗口网址
* @param 第二个参数:类似于a标签的target属性,是替换当前窗口还是新开一个窗口
* @param 第三个参数:新窗口特征:大小和位置等(新窗口才有效_blank)
* @param 第四个参数:布尔类型 true/false:把新开的窗口加入/不加入到浏览器历史记录
* @return 新打开的window对象
*/
let newWindow = window.open('https://www.baidu.com', '_blank', 'top=100,left=100,width=500,height=300', true );
}
//关闭窗口
document.getElementById('close').onclick = function ( ) {
//参数就是你想要关闭的窗口对象,如果不写,默认就是关闭自己
//1.这样写如果关闭的是顶级窗口谷歌和火狐会失效,如果失效可以使用下面这种写法
//window.close( );
/*2.谷歌火狐为了安全起见会拦截我们的代码,js代码只能关闭用js代码打开的界面,
所以我们用js先假装在当前窗口打开自己,然后再关闭自己*/
//这里的url不是空字符串"",而是一个空格字符串 " "
window.open(" ","_self").close();
}
</script>
</html>
1.3-window对象三个事件
window对象有三个事件,记录了浏览器窗口从打开到关闭的三个过程
- 1.window.onload:界面上所有的内容加载完毕之后才触发这个事件
- 2.window.onbeforeunload:界面在关闭之前会触发这个事件
3.window.onunload:界面在关闭的那一瞬间会触发这个事件
- 点击某个离开页面的链接
- 在地址栏中键入了新的 URL
- 使用前进或后退按钮
- 关闭浏览器窗口
- 重新加载页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<script>
/*window对象有三个事件,记录了浏览器窗口从打开到关闭的三个过程
1.window.onload:界面上所有的内容加载完毕之后才触发这个事件
2.window.onbeforeunload:界面在关闭之前会触发这个事件
3.window.onunload:界面在关闭的那一瞬间会触发这个事件
*/
//由于我们script标签写在了body标签的上面,这行代码会在body内容还未加载的时候就执行
console.log ( document.getElementById ( "p1" ) );//null 此时编译器还未解析p标签
//1.window.onload:界面上所有内容加载完毕后会触发
window.onload = function ( ) {
// 由于编译器是从上往下解析html文件的,如果我们的js代码写在body前面,就有可能无法获取dom对象
console.log ( "当前界面全部加载完毕" );
//window.onload无论写在界面什么位置都是等整个界面加载完毕之后才会执行
console.log ( document.getElementById ( "p1" ) );
}
//2.window.onbeforeunload:界面在关闭前触发
window.onbeforeunload = function ( ) {
/*
* 1.这个方法主要用于在界面关闭之前保存一些重要数据
* 2.也可以弹出一个提示框挽留一下用户
* */
//return 内容:浏览器会自动弹出一个挽留窗口
//谷歌和火狐都会拦截这种恶心事,只有IE支持
return '你真的要狠心抛弃我吗';
}
//3 window.onunload:界面关闭时触发
window.onunload = function ( ) {
console.log('界面正在关闭');
}
// 注意:如果打开的页面没有任何操作,那么关闭系统也会忽略onbeforeunload、onunload事件(里面的log会执行,但是不会有弹出框提示)
// 另外,弹出窗口的内容chrome和ff已经不可更改
</script>
<body>
<p id="p1">我是p标签</p>
</body>
</html>
1.4-location对象
1.location对象:包含当前页面的URL信息
- url:全球统一资源定位符
- url = 协议名(http) + ip地址(域名) + 端口号 + 资源路径
- 暂时只需要知道location对象包含一个网页的网络url信息即可,具体的含义将在后面阶段学习网络的时候详细讲解
2.location对象有三个常用的方法
- (1)打开新网页:location.assign(‘你要打开的新网页的url’)
- (2)替换当前网页:location.replace(‘要替换的网页url’)
- (3) 刷新当前网页: location.reload()
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<input type="button" id="assign" value="assign打开新网页">
<br>
<input type="button" id="replace" value="replace替换当前网页">
<br>
<input type="button" id="reload" value="reload刷新当前网页">
<br>
</body>
<script>
/*1.location对象:包含当前页面的URL信息
* url:全球统一资源定位符
* url = 协议名(http) + ip地址(域名) + 端口号 + 资源路径
* 暂时只需要知道location对象包含一个网页的网络url信息即可,具体的含义将在后面阶段学习网络的时候详细讲解
2.location对象有三个常用的方法
* (1)打开新网页:location.assign('你要打开的新网页的url')
* (2)替换当前网页:location.replace('要替换的网页url')
* (3) 刷新当前网页: location.reload()
*/
//1.location对象信息查看
console.log ( window.location ); //location对象
console.log(location.hash); //资源定位符(锚点定位)
console.log(location.host); //主机 host = hostname + port
console.log(location.hostname); //主机名(ip地址)
console.log(location.port); //端口号
console.log(location.href); //完整的url路径
console.log(location.pathname); //资源路径
console.log(location.protocol); //url的协议
console.log(location.search); //url请求的参数
//2.assign:打开新网页
document.getElementById('assign').onclick = function ( ) {
//会留下历史记录(可以回退)
window.location.assign('http://www.itheima.com');
//上面这行代码等价于下面这行代码
//window.location.href = 'http://www.itheima.com';
}
//3.replace:替换当前网页
document.getElementById('replace').onclick = function ( ) {
//不会留下历史记录(不能回退)
window.location.replace('http://www.itcast.com');
}
//4.刷新当前网页
document.getElementById('reload').onclick = function ( ) {
//相当于按了F5刷新当前网页
window.location.reload();
}
</script>
</html>
1.5-history对象
history对象主要用于记录你当前窗口的历史记录
- 主要作用就是前进和后退网页(相当于浏览器的左上角前进后退按钮功能)
- history.forward():前进
- history.back():后退
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<a href="09-history测试页.html">点我跳转</a>
<input type="button" value="前进" id="forword">
</body>
<script>
/*history对象主要用于记录你当前窗口的历史记录
* 主要作用就是前进和后退网页(相当于浏览器的左上角前进后退按钮功能)
* history.forward():前进
* history.back():后退
*/
document.getElementById('forword').onclick = function ( ) {
//跳转到当前网页历史记录的下一页,如果没有下一页的历史记录,则不跳转
history.forward();
}
</script>
</html>
1.6-navigator对象
navigator对象:包含当前浏览器的信息
- 工作中应用场景:用户信息统计(统计我这个网站平台的用户群体分布,什么浏览器,windows什么版本等)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
</body>
<script>
/*navigator对象:包含当前浏览器的信息
工作中应用场景:用户信息统计(统计我这个网站平台的用户群体分布,什么浏览器,windows什么版本等)
*/
console.log ( navigator );//navigator对象
console.log ( navigator.appVersion ); //当前浏览器版本信息
console.log ( navigator.platform ); //当前浏览器的硬件平台
console.log ( navigator.userAgent ); //当前浏览器信息
//使用场景1:判断当前用户的操作系统是32位还是64位
//谷歌和IE 64位显示WOW64 火狐显示Win64
if(navigator.userAgent.indexOf('WOW64') != -1 || navigator.userAgent.indexOf('Win64') != -1){
console.log ( "64位" );
}else{
console.log ( "32位" );
}
//使用场景2:判断用户当前使用哪种浏览器
if(navigator.userAgent.indexOf('Chrome') != -1){
console.log ( "谷歌浏览器" );
}else if(navigator.userAgent.indexOf('Firefox') != -1){
console.log ( "火狐浏览器" );
}else{
console.log ( "IE浏览器" ); //也有可能是其他小众浏览器,可以忽略不计
}
</script>
</html>