Web前端学习总结第六周
JavaScript
一、操作元素
1、排他思想
如果有一组元素,想让某一个元素实现某种样式,需要用到循环的排他思想算法:
- 所有元素全部清除样式(干掉其他人)
- 给当前元素设置样式(留下我自己)
- 注意顺序不能颠倒,首先干掉其他人,在设置自己
案例解释:
var btns = document.getElementsByTagName('button');
for (var i = 0; i < btns.length; i++){
btns[i].onclick = function() {
for (var i = 0; i < btns.length; i++) {
btns[i].style.backgroundColor = '';
}
this.style.backgroundColor = 'pink';
}
}
2、全选和取消全选的算法
// 1. 全选和取消全选做法: 让下面所有复选框的checked属性(选中状态) 跟随 全选按钮即可
// 获取元素
var j_cbAll = document.getElementById('j_cbAll'); // 全选按钮
var j_tbs = document.getElementById('j_tb').getElementsByTagName('input'); // 下面所有的复选框
// 注册事件
j_cbAll.onclick = function() {
// this.checked 它可以得到当前复选框的选中状态如果是true 就是选中,如果是false 就是未选中
console.log(this.checked);
for (var i = 0; i < j_tbs.length; i++) {
j_tbs[i].checked = this.checked;
}
}
// 2. 下面复选框需要全部选中, 上面全选才能选中做法: 给下面所有复选框绑定点击事件,每次点击,都要循环查看下面所有的复选框是否有没选中的,如果有一个没选中的, 上面全选就不选中。
for (var i = 0; i < j_tbs.length; i++) {
j_tbs[i].onclick = function() {
// flag 控制全选按钮是否选中
var flag = true;
// 每次点击下面的复选框都要循环检查者4个小按钮是否全被选中
for (var i = 0; i < j_tbs.length; i++) {
if (!j_tbs[i].checked) {
flag = false;
break; // 退出for循环 这样可以提高执行效率 因为只要有一个没有选中,剩下的就无需循环判断了
}
}
j_cbAll.checked = flag;
}
}
3、自定义属性的操作
(1)获取属性值
- element.属性 获取属性值
- element.getAttribute(‘属性’);
区别:
- element.属性 获取内置属性值(元素内部自带的属性)
- element.getAttribute(‘属性’); 主要获得自定义的属性(标准)我们自己定义的属性
(2)设置属性值
- element.属性 = ‘值’ 设置内置属性值
- element.getAttribute(‘属性’,‘值’);
区别:
- element.属性 设置内置属性值
- element.getAttribute(‘属性’); 主要设置自定义的属性(标准)
(3)删除属性值
element.removeAttribute(‘属性’);
4、tab栏切换
// 获取元素
var tab_list = document.querySelector('.tab_list');
var lis = tab_list.querySelectorAll('li');
var items = document.querySelectorAll('.item');
// for循环绑定点击事件
for (var i = 0; i < lis.length; i++) {
// 开始给5个小li 设置索引号
lis[i].setAttribute('index', i);
lis[i].onclick = function() {
// 1. 上的模块选项卡,点击某一个,当前这一个底色会是红色,其余不变(排他思想) 修改类名的方式
// 干掉所有人 其余的li清除 class 这个类
for (var i = 0; i < lis.length; i++) {
lis[i].className = '';
}
// 留下我自己
this.className = 'current';
// 2. 下面的显示内容模块
var index = this.getAttribute('index');
console.log(index);
// 干掉所有人 让其余的item 这些div 隐藏
for (var i = 0; i < items.length; i++) {
items[i].style.display = 'none';
}
// 留下我自己 让对应的item 显示出来
items[index].style.display = 'block';
}
}
5、H5自定义属性
自定义属性目的:是为了保存并使用数据。有些数据可以保存到页面中而不用保存到数据库中。
(1)设置H5自定义属性
H5规定自定义属性data-开头做为属性名并且赋值。
比如 data-index= “1” 或者element.setAttribute( ‘data-index’ ,2)
(2)获取H5自定义属性
1、兼容性获取 element.setAttribute( ‘data-index’ );
2、H5新增element.dataset.index 或者 element.dataset[‘index’]
二、节点操作
利用DOM提供的方法获取元素逻辑性不强且繁琐,利用节点 层级关系获取元素,利用父子兄节点关系获取,逻辑性强但兼容性差,这两种方式都可以获取元素节点,但是节点操作更简单。
网页中所有内容都是节点(标签、属性、文本、注释等),在DOM中节点用node来表示。一般地,节点至少拥有nodeType(节点类型)、nodeName(节点名称)和nodeValue(节点值)这三个基本属性。
- 元素节点 nodeType 为 0
- 属性节点 nodeType 为 2
- 文本节点 nodeType 为 3(文本节点包含文字、空格、换行)
1、节点层级
(1)父级节点
node.parentNode
- parentNode 属性可返回某节点的父节点,注意是最近的一个父节点
- 如果指定的节点没有父节点则返回null
(2)子节点
parentNode.children(非标准)
parentNode.children 是一个只读属性,返回所有的子元素节点。它只返回子元素节点,其余节点不返回。
parentNode.firstElementChild
firstElementChild返回第一个子元素节点,找不到则返回null
parentNode.lastElementChild
lastElementChild返回最后一个子元素节点,找不到则返回null
实际开发的写法,既没有兼容性又可以返回子节点
//返回第一个子节点
children[0]
//返回最后一个子节点
children[parentNode.children.length - 1]
(3)兄弟节点
node.nextElementSibling
返回当前元素的下一个兄弟元素节点,找不到则返回null
node.previousElementSibling
返回当前元素上一个兄弟节点,找不到则返回null
上述语句都是有兼容性的,下面是解决兼容性问题的方法:
function getNextElementSibling(element) {
var el = element;
while (el = el.nextSibling) {
if (el.nodeType === 1) {
return el;
}
}
return null;
}
2、操作节点方法
(1)创建节点
document.createElement('tagName')
因为创建的元素原本是不存在的,是根据我们的需求动态生成的,所以我们也称为动态创建元素节点。
(2)添加节点
node.appendChild(child)
该方法将一个节点添加到指定父节点的子节点列表末尾,切记括号里没有引号。
node.insertBeforeChild(child,指定元素)
将一个节点添加到指定父节点的子节点前面
(3)删除节点
node.removeChild()
从DOM中删除一个节点,返回删除的节点,括号中也没有引号。
(4)复制节点
node.cloneNode()
返回调用该方法的节点的一个副本,克隆了但不会添加到页面需要用添加语句实现。
注意:
- 如果括号里的参数为空或者为false,则是浅拷贝,即只克隆复制节点本身 ,不克隆里面的子节点。
- 如果括号里的参数为true,则是深度拷贝,会复制节点本身以及里面所有的子节点。
三、事件高级
1、注册事件
注册事件的方式有两种一种是传统方式另一种是方法监听注册事件。方法监听注册事件的特点就是同一个元素同一事件可以注册多个监听器,按照注册事件依次执行。
eventTarget.addEventListener(type, listener[, useCapture])
eventTarget.addElementListener()方法将指定的监听器注册到eventTarget(目标对象)上,当该对象触发指定事件时,就会执行事件处理函数。
该方法接受到的三个参数:
- type:事件类型字符,比如click,mouseover,z注意这里不要带on
- listener:事件处理函数,事件发生时,会调用监听函数
- useCapture:可选参数,是一个布尔值,默认是false
2、删除事件
1、传统注册方式
eventTarget.onclick = null;
2、方法监听注册方式
eventTarget.removeEventListener(type, listener[, useCapture])
这里删除需要用命名函数。
3、DOM事件流
事件流描述的是从页面中接受事件的顺序。
事件发生时会在元素节点之间按照特定顺序传播,这个过程就叫做DOM事件流。
DOM事件流分为3个阶段:
- 捕获阶段
- 当前目标阶段
- 冒泡阶段
4、事件对象
eventTarget.onclick = function(event) {}
eventTarget.addEventListener('click', function(event) {})
//我们习惯将event写成e
事件发生后,跟事件相关的一系列信息数据的集合都放在这个对象里面,这个对象就是事件对象,它有很多属性和方法。这个event是个形参,系统帮我们创建的,不需要我们传递实参过去。
事件对象中常见的属性和方法
事件对象属性方法 | 说明 |
---|---|
e.target | 返回触发事件的对象 |
e.type | 返回事件类型 |
e.preventDefault | 阻止默认事件比如不让连接跳转 |
e.stopPropagation | 阻止冒泡 |
这里需要注意e.target和this的区别,e.target点击了哪个元素,就返回哪个元素,this哪个元素绑定了这个点击事件,那么就返回哪个谁
5、事件委托
原理
不是每个子节点单独设置事件监听器,而是事件监听器设置在其父节点上,然后利用冒泡原理影响设置每个节点。
作用
我们只操作了一次DOM,提高了程序的性能。
6、常用鼠标事件
(1)、禁止鼠标右键菜单
contextmenu主要控制应该何时显示上下文菜单,主要用于程序员取消默认的上下文菜单
document.addEventListener('contextmenu', function(e) {
e.preventDefault();
})
(2)、禁止鼠标选中(selectstart 开始选中)
document.addEventListener('selectstart', function(e) {
e.preventDefault();
})
(3)、鼠标事件对象
event对象代表事件的状态,跟事件相关的一系列信息的集合。
鼠标事件对象 | 说明 |
---|---|
e.clientX | 返回鼠标相对于浏览器窗口可视区的X坐标 |
e.clientY | 返回鼠标相对于浏览器窗口可视区的Y坐标 |
e.pageX | 返回鼠标相对于文档页面的X坐标 |
e.pageY | 返回鼠标相对于文档页面的Y坐标 |
e.screenX | 返回鼠标相对于电脑屏幕的X坐标 |
e.screenY | 返回鼠标相对于电脑屏幕的Y坐标 |
7、常用键盘事件
键盘事件 | 触发条件 |
---|---|
onkeyup | 某个键盘按键被松开时触发 |
onkeydown | 某个键盘按键被按下时触发 |
onkeypress | 某个键盘按键被按下时触发 可以辨别大小写但是不识别功能键 |
keyCode | 返回该键的ASCII值 |
注意:
- 如果使用addEventListener不需要加on
- 三个事件的执行顺序时:keydown–keypress–keyup
总结案例
该案例实现的时放大搜索框内的内容,通过判断搜索框内的有无数据来判断是否需要弹出方法框。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
.search {
position: relative;
width: 178px;
margin: 100px;
}
.con {
display: none;
position: absolute;
top: -40px;
width: 171px;
border: 1px solid rgba(0, 0, 0, .2);
box-shadow: 0px 2px 4px rgba(0, 0, 0, .2);
padding: 5px 0;
font-size: 18px;
line-height: 20px;
color: #333;
}
.con::before {
content: '';
width: 0;
height: 0;
position: absolute;
top: 28px;
left: 18px;
border: 8px solid #000;
border-style: solid dashed dashed;
border-color: #fff transparent transparent;
}
</style>
</head>
<body>
<div class="search">
<div class="con">123</div>
<input type="text" placeholder="请输入您的快递单号" class="jd">
</div>
<script>
var con = document.querySelector('.con');
var jd_input = document.querySelector('.jd');
jd_input.addEventListener('keyup', function() {
if (this.value === '') {
con.style.display = 'none';
}else {
con.style.display = 'block';
con.innerHTML = this.value;
}
})
jd_input.addEventListener('blur', function() {
con.style.display = 'none';
})
jd_input.addEventListener('focus', function() {
if (this.value !== '') {
con.style.display = 'block';
}
})
</script>
</body>
</html>