目录
前言
Web APIS和JS基础关联性
JS为基础阶段:主要学习ECMAScript标准规定的基本语法,但是做不了常用的网页交互效果;
Web APIs阶段:Web APIs是W3C组织的标准,主要学习DOM和BOM,这部分是js独有的部分,主要是学习页面交互功能,但需要JS基础的课程内容做基础。
Web APIs是浏览器提供的一套操作浏览器功能和页面元素的API(BOM和DOM),主要针对浏览器提供的接口,用于做交互效果。
Web APIs一般都有输入和输出(函数的传参和返回值),Web APIs很多都是方法(函数);
一句话总结:JS基础学习、ECMAScript基础语法为后面做铺垫,Web APIs是JS的应用,大量使用JS基础语法做交互效果。
DOM
DOM(Document ObjectModel,简称DOM),是W3C组织推荐的处理可扩展标记语言(HTML或XML)的标准编程接口;
W3C已经定义了一系列的DOM接口,通过这些DOM接口可以改变网页的内容、结构和样式;
DOM树有如下定义:
文档:一个页面就是一个文档,DOM中使用document表示;
元素:页面中的所有标签都是元素,DOM中使用element表示;
节点:网页中的所有内容都是节点(如标签、属性、文本、注释等),DOM中使用node表示;
注意:DOM中如上所有内容都看做对象;
获取DOM元素
有四种方式获取DOM元素:根据ID获取、根据标签名获取、通过HTML5新增的方法获取、特殊元素获取。
- 根据ID获取
使用getElementById()方法可获取带有ID的元素对象。
<body>
<div id = 'ids'>今天不上班</div>
</body>
<script>
var ids = document.getElementById('ids')
console.log(ids); // <div id = 'ids'>今天不上班</div>
</script>
- 根据标签名获取
使用getElementsByTagName()方法可返回带有指定标签名的对象的集合。
返回的是带有指定标签名的对象的集合(伪数组形式);所以操作里面的元素需要遍历;
<body>
<ul>
<li>好好学习</li>
<li>天天向上</li>
<li>报效祖国</li>
</ul>
</body>
<script>
var tag = document.getElementsByTagName('li')
console.log(tag);
for (var i = 0; i < tag.length; i++) {
console.log(tag[i]);
}
</script>
- 通过HTML5新增的方法获取
使用document.getElementsByClassName('类名'),根据类名返回元素对象集合(获取的也是伪数组形式);此处方法参数类名中不用加符号.
<body>
<div class="name">李雷和韩梅梅</div>
</body>
<script>
var nm = document.getElementsByClassName('name');
console.log(nm);
</script>
使用document.querySelector('选择器'),根据指定选择器返回第一个元素对象;querySelector里面的参数要注意选择器需要加符号,如类选择器为.类选择器
<body>
<div class="name">李雷和韩梅梅</div>
<div class="name">语文和数学</div>
</body>
<script>
var nms = document.querySelector('.name');
console.log(nms); // <div class="name">李雷和韩梅梅</div>
</script>
使用document.querySelectorAll('选择器')返回指定选择器的所有元素对象集合;
<body>
<div class="name">李雷和韩梅梅</div>
<div class="name">语文和数学</div>
</body>
<script>
var nms = document.querySelectorAll('.name'); // 是一个伪数组
console.log(nms);
</script>
- 特殊元素(body、html)获取
获取body元素:document.body(一切都包含在里面,包括空格、注释等);
<body>
<div class="name">语文和数学</div>
<script>
// 获取body元素
var bodys = document.body;
console.log(bodys);
</script>
</body>
获取html元素:document.documentElement; // html标签内的都会包含在里面;
事件
事件概述
JavaScript使得有能力创建动态页面,而事件是可以被JavaScript侦测到的行为(触发---响应机制);
例如:网页中的每个元素都可以产生某些可以触发JavaScript的事件,例如:在用户点击某按钮时产生一个事件,然后去执行某些操作;
事件有三部分组成 事件源 事件类型 事件处理程序,也被称为事件三要素;
事件源:即事件被触发的对象,一般是按钮;
事件类型:即通过何种方式触发事件,如鼠标经过还是鼠标点击,或是键盘按下;
事件处理程序:一般是通过函数赋值的方式完成;
<body>
<!-- 事件源 按钮 -->
<button id='btn'>点我!</button>
</body>
<script>
// 事件源 按钮
var btn = document.getElementById('btn');
// 事件类型及事件处理
btn.onclick = function() {
alert('猜猜我是谁!')
}
</script>
基于此,执行事件的步骤如下:
1、获取事件源
2、注册事件(绑定事件)
3、添加事件处理程序(采取函数赋值形式);
常见的鼠标事件如下:
鼠标事件 | 触发条件 |
onclick | 鼠标点击左键触发 |
onmouseover | 鼠标经过触发 |
onmouseout | 鼠标离开触发 |
onfocus | 获得鼠标焦点触发 |
onblur | 失去鼠标焦点触发 |
onmousemove | 鼠标移动触发 |
onmouseup | 鼠标弹起触发 |
onmousedown | 鼠标按下触发 |
注册事件(绑定事件)
给元素添加事件,称为注册事件或绑定事件;
注册事件有两种方式:传统方式和方法监听注册方式
传统注册方式:
利用on开头的事件,如onclick、onmouseover等
<body>
<button>点我</button>
<script>
var btn = document.querySelector('button');
btn.onclick = function() {
alert("点我干什么~") // 该警示框不会被弹出
}
btn.onclick = function() {
alert("你猜谁会弹出~") // 该警示框会被弹出
}
</script>
</body>
特点:注册事件的唯一性:同一个元素同一事件只能设置一个处理函数,最后注册的处理函数将会覆盖前面注册的处理函数(即只能绑定一个函数);
方法监听注册方式:
该方式是w3c标准的推荐方式,注意:addEventListener()它是一个方法,ie9之前的只支持addEvent()方法;
- addEventListener()方法
特点:同一个元素同一个事件可以注册多个监听器,会按注册事件的注册顺序依次执行;
eventTarget.addEventListener(type, Listener[, useCapture])
该方法将指定的监听器(监听器即事件处理函数)注册到eventTarget(目标对象)上,当该对象触发指定的事件时,就会执行事件处理函数;
该方法接收三个参数:
type:事件类型字符串,如click、mouseover等,此处事件类型不要带on!
listener: 即事件处理函数,当事件发生时,则会调用该监听函数;
useCapture:是可选参数,用布尔值表示,默认是false,设置为false,则为冒泡阶段,若为true则为捕获阶段;
<body>
<button>点我</button>
<button>还是点我吧</button>
<script>
var btn = document.querySelectorAll('button');
btn[1].addEventListener('click', function() {
alert('我能弹出!') // 该警示框能弹出
})
btn[1].addEventListener('click', function() {
alert('我也能弹出!') // 该警示框也能弹出
})
</script>
</body>
- attachEvent事件监听方式
eventTarget.attachEvent(eventNameWithOn,callback)
该方法将指定的监听器注册到eventTarget(目标对象)上,当该对象触发指定的事件时,指定的回调函数就会被执行。
该方法接收两个参数:
eventNameWithOn:事件类型字符串,如onclick、onmouseover,注意:要带上on
callback:事件处理函数,当目标触发事件时回调函数被调用;
<body>
<button>试试我</button>
<script>
btn[2].attachEvent('onclick', function() {
alert('在ie9之前搞定~')
})
</script>
</body>
兼容性方法:
function addEventListener(element, eventName, fn) {
// 判断当前浏览器是否支持addEventListener方法
if(element.addEventListener) {
element.addEventListener(eventName, fn);
} else if (element.attachEvent) {
element.attachEvent("on" + eventName, fn);
} else {
// 相当于 element.onclick = fn
element['on' + eventName] = fn;
}
}
删除事件(解绑事件)
传统注册方式:
eventTarget.onclick = null;
方法监听注册方式:
eventTarget.removeEventListener(type,listener[, useCapture]); // 方法一
eventTarget.detachEvent(evnetNameWithOn, callback); // 方法二 适用于低版本浏览器
方法监听注册方式在注册事件时,监听器最好不要设置为匿名函数,否则这里的listener还要写一遍匿名函数,并且函数不用加小括号(),如fn1不写成fn1
<body>
<button>点我</button>
<button>还是点我吧</button>
<button>试试我</button>
<script>
var btn = document.querySelectorAll('button');
btn[0].onclick = function() {
alert("点我干什么~"); // 移除事件后,该警示框只会做到第一次点击弹出,再点击不会弹出
btn[0].onclick = null;
}
btn[1].addEventListener('click', fn1);
function fn1() {
alert('我也能弹出!'); // 移除事件后,该警示框只会做到第一次点击弹出,再点击不会弹出
btn[1].removeEventListener('click', fn1)
}
btn[2].attachEvent('onclick', fn2);
</script>
</body>
兼容性删除事件方法:
function removeEventListener(element, eventName, fn) {
// 判断当前浏览器浏览器是否支持removeEventListener方法
if (element.removeEventListener) {
element.removeEventListener(eventName, fn);
} else if (element.detachEvent) {
element.detachEvent('on' + eventName, fn);
} else {
element['on' + eventName] = null;
}
}
DOM事件流
事件流描述的是从页面中接收事件的顺序。
事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即DOM事件流;
如给一个按钮注册了点击事件:
DOM事件流分为3个阶段:
1、捕获阶段 2、当前目标阶段 3、冒泡阶段
事件冒泡:IE最早提出,事件开始时由最具体的元素接收,然后逐级向上传播到DOM最顶级节点的过程
事件捕获:网景最早提出,由DOM最顶层节点开始,然后逐级向下传播到最具体的元素接收的过程;
注意:
JS代码中只能执行捕获或者冒泡其中的一个阶段;
传统注册方式和attachEvent方式只能得到冒泡阶段;
addEventListener(type, listener[, useCapture])第三个参数useCapture若是true,表示在事件捕获阶段调用事件处理程序;若是false(不写默认就是false),表示在事件冒泡阶段调用事件处理程序;
实际开发中,很少使用事件捕获,更关注事件冒泡;
有些事件是没有冒泡的,如onblur、onfocus、onmouseover
<body>
<div class='father'>这是一个测试案例
<div class='son'>点我</div>
</div>
<script>
var divs = document.querySelectorAll('div');
// 将useCapture设置为true,为捕获阶段,则从顶层往下传递
divs[0].addEventListener('click', function() {
alert('这是父级标签~');
}, true)
divs[1].addEventListener('click', function() {
alert('这是子级标签~');
}, true)
// 此时点击父级内容,则只弹出'这是父级标签'
// 点击子级内容,则先弹出父级标签,再弹出子级标签
</script>
</body>
<body>
<div class='father'>这是一个测试案例
<div class='son'>点我</div>
</div>
<script>
var divs = document.querySelectorAll('div');
// 将useCapture设置为false,为冒泡阶段,则从底层往上传递
divs[0].addEventListener('click', function() {
alert('这是父级标签~');
}, false)
divs[1].addEventListener('click', function() {
alert('这是子级标签~');
}, false)
// 此时点击父级内容,则只弹出'这是父级标签'
// 点击子级内容,则先弹出父级标签,再弹出子级标签
</script>
</body>
事件对象
event对象代表事件的状态,如键盘按键的状态、鼠标的位置、鼠标按钮的状态等;即事件发生后,跟事件相关的一系列信息数据的集合都放在这个对象里面,该对象即事件对象event,它有很多属性和方法,如:
谁绑定了这个事件;
鼠标触发事件的话,会得到鼠标的相关信息,如鼠标位置;
键盘触发事件的话,会得到键盘的相关信息,如按了哪个键;
事件对象的使用语法
eventTarget.onclick = function(event) {
// 这个event就是事件对象,可以将其写成e或evt
}
该event是个形参,系统帮我们设定为事件对象,不需要传递实参过去,该event对象在注册事件时自动创建,并依次传递给事件监听器(事件处理函数)
事件对象的兼容性方案
事件对象本身的获取存在兼容问题:
1、标准浏览器中是浏览器给方法传递的参数,只需要定义形参e(event)就可以获取到;
2、在IE6-8中,浏览器不会给方法传递参数,若需要的话,需要到window.event中获取查到;
解决: e = e || window.event;
常见事件对象的属性和方法
事件对象属性方法 | 说明 |
e.target | 返回触发事件的对象 (标准) |
e.srcElment | 返回触发事件的对象 (非标准 ie6-8使用) |
e.type | 返回事件的类型 如click mouseover等 (不加on) |
e.cancelBubble | 该属性阻止冒泡 (非标准 ie6-8使用) |
e.preventDefault() | 该方法阻止默认事件 (标准,如不让链接跳转) |
e.ruturnValue | 该属性阻止默认事件 (非标准,如不让链接跳转) |
e.stopPropagation() | 阻止传播,不管是冒泡还是捕获阶段 |
e.stopImmediatePropagation | 一个节点同时绑定多个同类事件,阻止同类事件 |
-
e.target
e.target返回触发事件的对象(元素) 注意:和eventTarget不是一回事,eventTarget是事件绑定的对象;如下示例:
<body>
<ul>
<li>小红</li>
<li>小明</li>
</ul>
<script>
var ul = document.querySelector('ul');
ul.onclick = function(e) {
alert('看看是谁处理~');
console.log(e.target); // 可以是ul下的任意一个元素触发,如<li>小红</li>
console.log(this); // 因为事件绑定在ul上,此时this即ul
}
</script>
</body>
- e.type
e.type返回事件对象的属性和方法
<body>
<button>测试</button>
<script>
var button = document.querySelector('button');
button.addEventListener('click', fun);
function fun(e) {
alert('111');
console.log('这是一个测试');
console.log(e.type); // click
}
</script>
</body>
-
阻止默认事件产生e.preventDefault()、e.returnValue
e.preventDefault()方法和e.returnValue属性阻止默认行为的发生,如让链接不跳转,或者让提交按钮不提交;后者应用于低版本浏览器;
<body>
<a href="http:www.baidu.com">百度</a>
<script>
var as = document.querySelector('a');
as.addEventListener('click', function(e) {
// e.preventDefault(); // 不会在触发提交作用
e.returnValue; // 不会再触发提交作用,适用于低版本
})
</script>
</body>
禁止鼠标右键弹出菜单栏 contextmenu
contextmenu主要控制应该何时显示上下文菜单,主要用于程序员取消默认的上下文菜单
<script>
document.addEventListener('contextmenu', function(e) {
e.preventDefault(); // 则不会弹出右键菜单
})
</script>
禁止鼠标选中selectStart
selectStart用于鼠标开始选中
<body>
<div>selectstart阻止了,则内容就不能被选中</div>
<script>
document.addEventListener('selectstart', function(e) {
e.preventDefault(); // 则页面内容就不会被选中,不能用于复制功能
})
</script>
</body>
-
阻止事件冒泡e.stopPropagation()、e.cancelBubble
阻止事件冒泡有两种方式,一种是利用事件对象里面的stopPropagation方法;另一种是使用事件对象的cancelBubble属性(适用于低版本浏览器);
<body>
<div class='father'>这是一个测试案例
<div class='son'>点我</div>
</div>
<script>
var divs = document.querySelectorAll('div');
// 将useCapture设置为true,为捕获阶段,则从顶层往下传递
divs[0].addEventListener('click', function() {
alert('这是父级标签~');
}, false)
divs[1].addEventListener('click', function(e) {
alert('这是子级标签~');
e.stopPropagation();
}, false)
// 此时点击父级内容,则只弹出'这是父级标签'
// 点击子级内容,则只弹出子级标签,不会再弹出父级标签
</script>
</body>
事件委托(代理、委派)
事件委托也称为事件代理,在jQuery里面称为事件委派;
原理:不对每个子节点设置事件监听器,而是事件监听器设置在父级节点上,然后利用冒泡原理影响设置每个子节点。
作用:只操作了一次DOM,提高了程序的性能;
<body>
<ul>
<li>小红</li>
<li>小明</li>
</ul>
<script>
var ul = document.querySelector('ul');
ul.addEventListener('click', function(e) {
alert('只给ul设置点击事件,利用事件冒泡影响每个节点~');
})
</script>
</body>
常用的鼠标与键盘事件对象
鼠标事件对象MouseEvent和键盘事件对象KeyboardEvent
鼠标事件对象 | 说明 |
e.clientX | 返回鼠标相对于浏览器窗口可视区的X坐标 |
e.clientY | 返回鼠标相对于浏览器窗口可视区的Y坐标 |
e.pageX | 返回鼠标相对于文档页面(document)的X坐标 |
e.pageY | 返回鼠标相对于文档页面(document)的Y坐标 |
e.screenX | 返回鼠标相对于电脑屏幕的X坐标 |
e.screenY | 返回鼠标相对于电脑屏幕的Y坐标 |
<style>
img {
position: absolute;
height: 40px;
width: 40px;
}
</style>
<body>
<img src="imgs/draw.jpg" alt="">
<script>
// 实现图片跟随鼠标移动效果
// 核心原理是每次鼠标移动获得的坐标赋值给图片的left和top值
var img = document.querySelector('img');
document.addEventListener('mousemove', function(e) {
var x = e.pageX;
var y = e.pageY;
console.log(x, y);
img.style.left = x + 'px';
img.style.top = y + 'px'; // 这个一定要连接'px'
})
</script>
</body>
常用键盘事件 | 触发条件 |
onkeyup | 键盘按键被松开时触发 |
onkeydown | 键盘按键被按下时触发 |
onkeypress | 键盘按键被按下时触发(但是他不识别功能键,如ctrl) |
若使用addEventListener不需要加on;
keyup和keydown不识别大小写;
三个事件的执行顺序是:keydown---keypress---keyup
e.KeyCode可得到键盘按键的ASC码值;
以下代码实现如下功能(内容为空时只显示input框,有值时则放大显示):
<style>
.con {
display: none; */
font-size: 20px;
}
</style>
<body>
<div class='search'>
<div class="con">123</div>
<input class='index' type="text" placeholder="请输入您的快递单号">
</div>
<script>
// input输入值时,con显示input内对应的大号内容,若input为空,则隐藏con
var con = document.querySelector('.con');
console.log(con);
console.log(con.style);
var ipt = document.querySelector('input');
ipt.addEventListener('keyup', function() {
if (ipt.value === '') {
con.style.display = 'none';
} else {
con.style.display = 'block';
con.innerHTML = ipt.value;
}
})
</script>
</body>
操作元素
DOM操作可改变网页内容、结构和样式,可以利用DOM操作元素来改变元素里面的内容、属性等。
改变元素内容
可利用elment.innerText或element.innerHTML改变元素中的内容;前者改变从元素起始位置到终止位置的内容,但它去除html标签,同时空格和换行也会去掉;后者也可以改变元素从起始位置到终止的全部内容,但是它可改变标签中的html标签和空格、换行
<body>
<!-- 事件源 按钮 -->
<button id='btn'>点我!</button>
<div>早上好</div>
</body>
<script>
// 事件源 按钮
var btn = document.getElementById('btn');
var divs = document.querySelector('div');
// 事件类型及事件处理
btn.onclick = function() {
// 点击按钮后,使用innerHTML方法 div内容变为晚安~,并加粗显示
divs.innerHTML = '<strong>晚安~</strong>';
// 点击按钮后,使用innerText方法 div内容变为<strong>晚安~</strong>
divs.innerText = '<strong>晚安~</strong>';
}
</script>
改变常用元素的属性
可通过DOM改变元素的属性,如src、href、title等
<body>
<img src="imgs/draw.jpg" alt="">
<div>drawing~</div>
</body>
<script>
// 事件源 按钮
var div = document.querySelector('div');
var img = document.querySelector('img');
// 事件类型及事件处理
img.onclick = function() {
// 点击图片后,div内容变为working~,图片变为work.jpg
img.src = "imgs/work.jpg";
div.innerText = 'working~';
}
</script>
改变表单元素的属性
利用DOM可以改变表单元素的type/value/checked/selected/disabled属性;
注意表单里面的内容是通过value属性改变的~
<body>
<button>点我!</button>
<input type="text" value="请输入内容">
</body>
<script>
var btn = document.querySelector('button');
var ipt = document.querySelector('input');
btn.onclick = function() {
// 按钮点击后 表单文本改变
ipt.value = '起风了~';
// 按钮点击后 按钮被禁用,此处用this替代btn是因为该动作是btn执行的,this即表示btn
// this 指向的是事件函数的调用者
this.disabled = true;
}
</script>
改变元素的样式属性
可通过JS修改元素的大小、颜色、位置等样式;通过element.style改变行内样式,通过element.className改变类名样式;使用element.style方式改变样式时,要注意style里面的属性要改为驼峰命名方式,如之前的背景样式为background-color,此处应该为backgroundColor;如字体为font-size,此时应该为fontSize;由于利用JS修改样式,产生的是行内样式,所以权重较高~
自定义属性的操作
获取属性值的方法有:
- element.属性
- element.getAttribute('属性');
区别:
第一种方法用于获取元素本身自带的属性;后者主要是为了获取自定义的属性(标准),即程序员自定义的属性;
设置属性值的方法有:
element.属性 = “值” 用于设置内置元素的属性;
element.setAttribute('属性',‘值’) 用于设置自定义元素的属性;
移除属性:
element.removeAttribute('属性');
H5自定义属性:
自定义属性是为了保D:\fronted\pink\arraytest.html
D:\fronted\pink\1209.html存并使用数据,有些数据可以保存到页面中而不用保存到数据库中;
H5规定自定义属性要以data-开头作为属性名并且赋值;
<div data-index='1'></div>
// 或使用JS设置
element.setAttribute('data-index', 2);
获取H5自定义属性:
新增element.dataset.index或者element.dataset['index'], ie11才开始支持;
节点操作
为什么要学习节点操作?
获取元素通常有两种方式:
- 利用DOM提供的方法获取元素,如document.getElementById()、document.getElementsByClassName()、document.querySelector等,但该方式逻辑性不强、且比较繁琐;
- 利用节点层级关系获取元素,如利用父子兄节点关系获取元素、逻辑性强,但是兼容性较差;
节点概述
网页中的所有内容都是节点(如标签、属性、文本、注释等),在DOM中,节点使用node表示;
HTML DOM树中的所有节点均可通过JavaScript进行访问,所有HTML元素(节点)均可被修改,也可以创建或删除。
一般地,节点至少拥有nodeType(节点类型)、nodeName(节点名称)和nodeValue(节点值)这三个基本属性。
元素节点的nodeType为1;属性节点的nodeType为2;文本节点的nodeType为3(文本节点包含文字、空格、换行等),在实际开发中,节点操作主要操作的是元素节点。
节点层级
利用DOM树可把节点划分为不同的层级关系,常见的是父子兄层级关系。
- 父级节点 node.parentNode
parentNode属性可返回某节点的父节点,注意是最近的一个父节点,若指定的节点无父节点则返回null;
<body>
<div id = 'ids'>今天是个晴朗的日子</div> -->
<ul>
<li>好好学习</li>
<li>天天向上</li>
<li>报效祖国</li>
</ul>
</body>
<script>
var li = document.querySelector('li');
console.log(li);
var ul = li.parentNode;
console.log(ul);
</script>
- 子级节点 parentNode.childNodes(标准)
parentNode.childNodes返回包含指定节点的子节点的集合,该集合为即时更新的集合;子集合包含所有的子节点,如元素节点、文本节点等;
<body>
<div id = 'ids'>今天是个晴朗的日子</div> -->
<ul>
<li>好好学习</li>
<li>天天向上</li>
<li>报效祖国</li>
</ul>
</body>
<script>
var ul = document.querySelector('ul');
console.log(ul);
var li = ul.childNodes;
console.log(li); // 会把换行等一切子元素都查出来
</script>
如果只想要获得里面的元素节点(nodeType为1),则需要专门处理,所以一般不直接使用childNodes;
<body>
<div id = 'ids'>今天是个晴朗的日子</div> -->
<ul>
<li>好好学习</li>
<li>天天向上</li>
<li>报效祖国</li>
</ul>
</body>
<script>
var ul = document.querySelector('ul');
var arr = [];
console.log(ul);
for(var i = 0; i < ul.childNodes.length; i++) {
if(ul.childNodes[i].nodeType === 1) {
// console.log(ul.childNodes[i]);
arr.push(ul.childNodes[i]);
}
}
console.log(arr);
</script>
- 子级元素节点 parentNode.children(非标准)
parentNode.children是一个只读属性,返回所有的子元素节点。注意:该方法只返回子元素节点,其余节点类型不返回;
虽然该方法是一个非标准,但它得到了各个浏览器的支持,因此可以放心使用;
- 第一个子节点 parentNode.firstChild
parentNode.firstChild返回第一个子节点,找不到子节点则返回null。同样,也是包含所有的节点;
- 最后一个子节点 parentNode.lastChild
parentNode.lastChild返回最后一个子节点,找不到则返回null。同样,也是包含所有的节点;
- 第一个子元素节点 parentNode.firstElementChild
firstElementChild返回第一个子元素节点,找不到则返回null;ie9以上才支持
- 最后一个子元素节点 parentNode.lastElementChild
parentNode.lastElementChild返回最后一个子元素节点,找不到则返回null。ie9以上才支持
实际开发中,经常使用parentNode.children[索引]方法获得指定位置的子元素节点,如获取第一个子元素节点:parentNode.children[0]
获取最后一个子元素节点:parentNode.children[parentNode.children.length - 1];
- 当前元素的下一个兄弟节点node.nextSibling
node.nextSibling返回当前元素的下一个兄弟节点,找不到则返回null,返回的结果包含所有的节点;
- 当前元素的上一个兄弟节点node.previousSibling
node.previousSibling返回当前元素的上一个兄弟节点,找不到则返回null,返回的结果包含所有的节点;
- 当前元素的下一个兄弟元素节点 node.nextElementSibling
node.nextElementSibling返回当前元素下一个兄弟元素节点,找不到则返回null;ie9以上才支持
- 当前元素的下一个兄弟元素节点 node.nextElementSibling
node.previousElementSibling返回当前元素上一个兄弟元素节点,找不到则返回null;ie9以上才支持
所以要完美解决上述两种问题,要进行处理:
function getNextElementSibling(element) {
var el = element;
while(el = el.nextSibling) {
if(el.nodeType === 1) {
return el;
}
}
return null;
}
创建节点
- document.createElement('tagName')
document.createElement()方法创建由tagName指定的HTML元素,因为这些元素原先不存在,是根据我们的需求动态生成的,所以也称为动态创建元素节点;
添加节点
- node.appendChild(child)方法、 node.insertBefore(child,指定元素)
node.appendChild(child)方法将一个节点添加到指定父节点的子节点列表末尾。node是父节点;
node.insertBefore(child,指定元素)方法将一个节点添加到父节点的指定子节点前面。node是父节点;
<body>
<div id = 'ids'>今天是个晴朗的日子</div>
<ul>
<li>好好学习</li>
<li>天天向上</li>
<li>报效祖国</li>
</ul>
</body>
<script>
var ul = document.querySelector('ul');
var li = document.createElement('li');
var li1 = document.createElement('li');
// 在ul的最后一个li之后添加li1
ul.appendChild(li1);
// 在ul的第一个li之前添加li
ul.insertBefore(li,ul.children[0]);
console.log(ul);
</script>
删除节点
- 删除节点 node.removeChild(child)
node.removeChild(child)删除一个子节点,返回删除的节点。
复制节点
- 复制节点node.cloneNode()
node.cloneNode()方法返回调用该方法的节点的一个副本,也称为克隆节点/拷贝节点;
若参数为空或false,则是浅拷贝,即只克隆节点本身,不克隆里面的子节点;
若参数为true,则是深度拷贝,会复制节点本身及里面所有的子节点;
三种动态创建元素区别
document.write()是直接将内容写入页面的内容流,但是文档流执行完毕,会导致页面全部重绘(重绘是指重新创建一个页面,原先的页面都没了);
element.innerHTML是将内容写入某个DOM 节点,不会导致页面全部重绘;该方法创建多个元素效率更高(不要采用拼接字符串方式,采取数组形式拼接),但结构稍复杂;
createElement()创建多个元素效率稍低一点点,但是结构更清晰;
<body>
<div id = 'ids'>今天是个晴朗的日子</div>
<ul>
<li>好好学习</li>
<li>天天向上</li>
<li>报效祖国</li>
</ul>
</body>
<script>
var div = document.querySelector('div');
var date = +new Date();
// 采用拼接字符串形式
// for (var i = 0; i<1000;i++) {
// div.innerHTML += '<strong>心情好呀心情好</strong>';
// }
// var date1 = +new Date();
// var time = date1 - date;
// console.log(time); // 510ms
// 用数组形式形式
var arr = [];
for (var i = 0; i < 1000; i++) {
arr.push('<strong>心情好呀心情好</strong>');
}
div.innerHTML += arr.join('')
var date1 = +new Date();
var time = date1 - date;
console.log(time); // 1ms
</script>
示例
示例一:动态生成表格,点击删除按钮则会自动删除所在行
<body>
<!-- 表格应该只有头部,行和列都应该自动生成放在tbody下 -->
<table>
<thead>
<tr>
<td>姓名</td>
<td>性别</td>
<td>年龄</td>
<td>籍贯</td>
<td>操作</td>
</tr>
</thead>
<tbody>
</tbody>
</table>
</body>
<script>
// 动态生成表格
var datas = [{
name: '小唐',
sexual: '女',
age: '18',
nativePlace: 'SiChuan'
}, {
name: '小吴',
sexual: '男',
age: '20',
nativePlace: 'ShanDong'
}, {
name: '小阳',
sexual: '女',
age: '18',
nativePlace: 'AnHui'
}, {
name: '小曹',
sexual: '男',
age: '19',
nativePlace: 'HeNan'
}];
// 将数据依次放在tbody里面的行
var tbody = document.querySelector('tbody');
for (var i = 0; i < datas.length; i++) {
var tr = document.createElement('tr');
tbody.appendChild(tr);
for (var k in datas[i]) {
var td = document.createElement('td');
// 单元格存值
td.innerHTML = datas[i][k];
// 将单元格添加到行
tr.appendChild(td);
}
// 删除操作独立创建,使用href="javascript:;方法可以避免页面跳转,并且不会使链接上面加#"
var td1 = document.createElement('td');
td1.innerHTML = '<a href="javascript:;"> 删除 </a>'
tr.appendChild(td1);
}
// 点击删除按钮会删掉该行
var as = document.querySelectorAll('a');
for (var i = 0; i < as.length; i++) {
as[i].onclick = function() {
// as的父节点是td,td的父节点是tr,要删除tr(父亲的父亲)
// this.parentNode.parentNode.parentNode.removeChild(this.parentNode.parentNode);
tbody.removeChild(this.parentNode.parentNode);
}
}
</script>
示例二:在留言板上输入内容,发布后,自动显示留言列表
<body>
<input type="text"></input>
<button>发布</button>
<ul></ul>
</body>
<script>
// 留言板点击发布后,显示留言内容
var button = document.querySelector('button');
var ul = document.querySelector('ul');
var input = document.querySelector('input');
button.onclick = function() {
console.log(input.value);
if (input.value === '') {
alert('请先输入内容,再发布!');
return
} else {
var li = document.createElement('li');
li.innerHTML = input.value;
// 后发布的在留言板后面
ul.appendChild(li);
}
}
</script>
示例三:鼠标滑过显示下拉框内容
<style>
.nav,
.lili {
list-style: none;
float: left;
}
li {
list-style: none;
}
</style>
<body>
<ul class='nav'>
<li class='lili'>
<a href=" "> QQ</a>
<ul>
<li>
<a href="javascript:;">私信</a>
</li>
<li>
<a href="javascript:;">评论</a>
</li>
<li>
<a href="javascript:;">@我</a>
</li>
</ul>
</li>
<li class='lili'>
<a href="javascript:;"> 微博</a>
<ul>
<li>
<a href="javascript:;">私信</a>
</li>
<li>
<a href="javascript:;">评论</a>
</li>
<li>
<a href="javascript:;">@我</a>
</li>
</ul>
</li>
<li class='lili'>
<a href="javascript:;"> 微信</a>
<ul>
<li>
<a href="javascript:;">私信</a>
</li>
<li>
<a href="javascript:;">评论</a>
</li>
<li>
<a href="javascript:;">@我</a>
</li>
</ul>
</li>
</ul>
</body>
<script>
// 鼠标经过显示下拉菜单
var nav = document.querySelector('.nav');
var lis = nav.children;
for (var i = 0; i < lis.length; i++) {
lis[i].onmouseover = function() {
this.children[1].style.display = 'block';
}
lis[i].onmouseout = function() {
this.children[1].style.display = 'none';
}
}
</script>