DOM
文档:一个页面就是一个文档,DOM 中使用 document 表示
元素:页面中的所有标签都是元素,DOM 中使用 element 表示
节点:网页中的所有内容都是节点(标签、属性、文本、注释等),DOM 中使用 node 表示
获取元素
2.1 如何获取页面元素 获取页面中的元素可以使用以下几种方式:
根据 ID 获取
根据标签名获取
通过 HTML5 新增的方法获取
特殊元素获取
1、getElementById: 返回是是一个对象
2、getElementsByTagName获取某些元素:
1. 返回的是 获取过来的元素对象的集合 是以伪数组的形式存储的
2. 我们想要依次打印里面的元素对象我们可以采取遍历的方式
for (var i = 0; i < lis.length; i++) {
console.log(lis[i]);
}
3. 如果页面中只有一个li 返回的还是伪数组的形式
4. 如果页面中没有这个元素 返回的是空的伪数组的形式
父元素必须是指定的单个元素
var ol = document.getElementById('ol');
console.log(ol.getElementsByTagName('li'));
3、H5新增获取元素方式
1. getElementsByClassName 根据类名获得某些元素集合
var boxs = document.getElementsByClassName('box');
2. querySelector 返回指定选择器的第一个元素对象 切记 里面的选择器需要加符号 .box #nav
var firstBox = document.querySelector('.box');
console.log(firstBox);
3. querySelectorAll()返回指定选择器的所有元素对象集合
var allBox = document.querySelectorAll('.box');
console.log(allBox);
4、获取特殊元素
1.获取body 元素
var bodyEle = document.body;
2.获取html 元素
var htmlEle = document.documentElement;
事件三要素
事件源 事件类型 事件处理程序
(1) 事件源 事件被触发的对象 谁 按钮
(2) 事件类型 如何触发 什么事件 比如鼠标点击(onclick) 还是鼠标经过 还是键盘按下
(3) 事件处理程序 通过一个函数赋值的方式 完成
btn.onclick = function() {
alert('点秋香');
}
</script>
分时间显示不同案例
/ 1.获取元素
var img = document.querySelector('img');
var div = document.querySelector('div');
// 2. 得到当前的小时数
var date = new Date();
var h = date.getHours();
// 3. 判断小时数改变图片和文字信息
if (h < 12) {
img.src = 'images/s.gif';
div.innerHTML = '亲,上午好,好好写代码';
} else if (h < 18) {
img.src = 'images/x.gif';
div.innerHTML = '亲,下午好,好好写代码';
} else {
img.src = 'images/w.gif';
div.innerHTML = '亲,晚上好,好好写代码';
}
</script>
操作元素之改变元素内容
/
/ 当我们点击了按钮, div里面的文字会发生变化
1. 获取元素
var btn = document.querySelector('button');
var div = document.querySelector('div');
2.注册事件
btn.onclick = function() {
// div.innerText = '2019-6-6';
div.innerHTML = getDate();
}
3、函数
function getDate() {
var date = new Date();
// 我们写一个 2019年 5月 1日 星期三
var year = date.getFullYear();
var month = date.getMonth() + 1;
var dates = date.getDate();
var arr = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
var day = date.getDay();
return '今天是:' + year + '年' + month + '月' + dates + '日 ' + arr[day];
}
// 我们元素可以不用添加事件 那就是一刷新页面事件就会改变呢
var p = document.querySelector('p');
p.innerHTML = getDate();
</script>
innerText和innerHTML的区别
// innerText 和 innerHTML的区别
// 1. innerText 不识别html标签 非标准 去除空格和换行
var div = document.querySelector('div');
// div.innerText = '<strong>今天是:</strong> 2019';
// 2. innerHTML 识别html标签 W3C标准 保留空格和换行的
div.innerHTML = '<strong>今天是:</strong> 2019';
操作元素之修改元素属性
操作元素之表单属性设置
显示隐藏密码
<script>
// 1. 获取元素
var eye = document.getElementById('eye');
var pwd = document.getElementById('pwd');
// 2. 注册事件 处理程序
var flag = 0;
eye.onclick = function() {
// 点击一次之后, flag 一定要变化
if (flag == 0) {
pwd.type = 'text';
eye.src = 'images/open.png';
flag = 1; // 赋值操作
} else {
pwd.type = 'password';
eye.src = 'images/close.png';
flag = 0;
}
}
</script>
操作元素之修改样式属性
循环精灵图
显示隐藏文本框内容
<script>
// 1.获取元素
var text = document.querySelector('input');
// 2.注册事件 获得焦点事件 onfocus
text.onfocus = function() {
// console.log('得到了焦点');
if (this.value === '手机') {
this.value = '';
}
// 获得焦点需要把文本框里面的文字颜色变黑
this.style.color = '#333';
}
// 3. 注册事件 失去焦点事件 onblur
text.onblur = function() {
// console.log('失去了焦点');
if (this.value === '') {
this.value = '手机';
}
// 失去焦点需要把文本框里面的文字颜色变浅色
this.style.color = '#999';
}
</script>
排他思想
表格隔行变色
<script>
// 1.获取元素 获取的是 tbody 里面所有的行
var trs = document.querySelector('tbody').querySelectorAll('tr');
// 2. 利用循环绑定注册事件
for (var i = 0; i < trs.length; i++) {
// 3. 鼠标经过事件 onmouseover
trs[i].onmouseover = function() {
// console.log(11);
this.className = 'bg';
}
// 4. 鼠标离开事件 onmouseout
trs[i].onmouseout = function() {
this.className = '';
}
}
</script>
全选反选
<script>
// 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 就是未选中
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;
}
}
</script>
获得属性的两种方法
div.setAttribute('class', 'footer'); // class 特殊 这里面写的就是class 不是className
// 1. 获取元素的属性值
// (1) element.属性
console.log(div.id);
//(2) element.getAttribute('属性') get得到获取 attribute 属性的意思 我们程序员自己添加的属性我们称为自定义属性 index
console.log(div.getAttribute('id'));
console.log(div.getAttribute('index'));
// 2. 设置元素属性值
// (1) element.属性= '值'
div.id = 'test';
div.className = 'navs';
// (2) element.setAttribute('属性', '值'); 主要针对于自定义属性
div.setAttribute('index', 2);
// 3 移除属性 removeAttribute(属性)
div.removeAttribute('index');
</script>
H5自定义属性
console.log(div.getAttribute('getTime'));
div.setAttribute('data-time', 20);
console.log(div.getAttribute('data-index'));
console.log(div.getAttribute('data-list-name'));
// h5新增的获取自定义属性的方法 它只能获取data-开头的
// dataset 是一个集合里面存放了所有以data开头的自定义属性
console.log(div.dataset);
console.log(div.dataset.index);
console.log(div.dataset['index']);
// 如果自定义属性里面有多个-链接的单词,我们获取的时候采取 驼峰命名法
console.log(div.dataset.listName);
console.log(div.dataset['listName']);
</script>
</body>
节点概述
网页中的所有内容都是节点(标签、属性、文本、注释等),在DOM 中,
节点使用 node 来表示。
HTML DOM 树中的所有节点均可通过 JavaScript 进行访问,所有 HTML 元素(节点)均可被修改,也可以 创建或删除。
5.2 节点概述
一般地,节点至少拥有nodeType(节点类型)、nodeName(节点名称)和nodeValue(节点值)这三个 基本属性。
元素节点 nodeType 为 1
属性节点 nodeType 为 2
文本节点 nodeType 为 3 (文本节点包含文字、空格、换行等)
我们在实际开发中,节点操作主要操作的是元素节点
5.3 节点层级
利用 DOM 树可以把节点划分为不同的层级关系,常见的是父子兄层级关系
父节点操作
// 1. 父节点 parentNode
var erweima = document.querySelector('.erweima');
// 得到的是离元素最近的父级节点(亲爸爸) 如果找不到父节点就返回为 null
erweima.parentNode
</script>
子节点操作
// DOM 提供的方法(API)获取
var ul = document.querySelector('ul');
var lis = ul.querySelectorAll('li');
// 1. 子节点 childNodes 所有的子节点 包含 元素节点 文本节点等等
console.log(ul.childNodes);
console.log(ul.childNodes[0].nodeType);
console.log(ul.childNodes[1].nodeType);
// 2. children 获取所有的子元素节点 也是我们实际开发常用的
console.log(ul.children);
parentNode.children 是一个只读属性,返回所有的子元素节点。
它只返回子元素节点,其余节点不返 回 (这个是我们重点掌握的)。
虽然children 是一个非标准,但是得到了各个浏览器的支持,因此我们可以放心使用
子节点-第一个子元素和最后一个子元素
// 3. 实际开发的写法 既没有兼容性问题又返回第一个子元素
console.log(ol.children[0]);
console.log(ol.children[ol.children.length - 1]);
1. 如果想要第一个子元素节点,可以使用 \
parentNode.chilren[0]
2. 如果想要最后一个子元素节点,可以使用
parentNode.chilren[parentNode.chilren.length - 1]
创建和添加节点
document.createElement('tagName')
document.createElement() 方法创建由 tagName 指定的 HTML 元素。
因为这些元素原先不存在, 是根据我们的需求动态生成的,所以我们也称为动态创建元素节点。
// 1. 创建节点元素节点
var li = document.createElement('li');
// 2. 添加节点 node.appendChild(child)
node 父级 child 是子级 后面追加元素 类似于数组中的push
var ul = document.querySelector('ul');
ul.appendChild(li); child 是子级 后面追加元素 类似于数组中的push
// 3. 添加节点 node.insertBefore(child, 指定元素);
var lili = document.createElement('li');
ul.insertBefore(lili, ul.children[0]);
// 4. 我们想要页面添加一个新的元素 : 1. 创建元素 2. 添加元素
</script>
node.insertBefore() 方法将一个节点添加到父节点的指定子节点前面。类似于 CSS 里面的 before 伪元素。
2. node.insertBefore(child, 指定元素)
节点操作之删除节点
// 1.获取元素
var ul = document.querySelector('ul');
var btn = document.querySelector('button');
// 2. 删除元素 node.removeChild(child)
ul.removeChild(ul.children[0]);
3. 点击按钮依次删除里面的孩子
btn.onclick = function() {
if (ul.children.length == 0) {
this.disabled = true;
}
else {
ul.removeChild(ul.children[0]);
}
}
</script>
节点操作之克隆节点
var ul = document.querySelector('ul');
// 1. node.cloneNode();
括号为空或者里面是false 浅拷贝 只复制标签不复制里面的内容
// 2. node.cloneNode(true);
括号为true 深拷贝 复制标签复制里面的内容
var lili = ul.children[0].cloneNode(true);
ul.appendChild(lili);
三种创建元素方式区别
// }
// 三种创建元素方式区别
1. document.write() 创建元素
如果页面文档流加载完毕,再调用这句话会导致页面重绘
// var btn = document.querySelector('button');
// btn.onclick = function() {
// document.write('<div>123</div>');
// }
// 2. innerHTML 创建元素
var inner = document.querySelector('.inner');
for (var i = 0; i <= 100; i++) {
inner.innerHTML += '<a href="#">百度</a>'
}
// 拼接字符串 效率比较低
数组方式添加 最快
var arr = [];
for (var i = 0; i <= 100; i++) {
arr.push('<a href="#">百度</a>');
}
inner.innerHTML = arr.join('');
//join(''); 转化为字符串
3. document.createElement() 创建元素
var create = document.querySelector('.create');
for (var i = 0; i <= 100; i++) {
var a = document.createElement('a');
create.appendChild(a);
}
</script>
dom重点核心 增 删 改 查
1. document.write 2. innerHTML 3. createElement
6.2 增
1. appendChild 2. insertBefore
6.3 删
1. removeChild
6.4 改
主要修改dom的元素属性,dom元素的内容、属性, 表单的值等
1. 修改元素属性: src、href、title等
2. 修改普通元素内容: innerHTML 、innerText
3. 修改表单元素: value、type、disabled等
4. 修改元素样式: style、className
6.5 查
主要获取查询dom的元素
1. DOM提供的API 方法: getElementById、getElementsByTagName 古老用法 不太推荐
2. H5提供的新方法: querySelector、querySelectorAll 提倡
3. 利用节点操作获取元素: 父(parentNode)、子(children)、兄(previousElementSibling、 nextElementSibling) 提倡
6.6 属性操作
主要针对于自定义属性。
1. setAttribute:设置dom的属性值
2. getAttribute:得到dom的属性值
3. removeAttribute移除属性
6.7 事件操作
给元素注册事件, 采取 事件源.事件类型 = 事件处理程序
注册事件两种方式
扫描二维码关注公众号,回复:
12906212 查看本文章

attachEvent
3. attachEvent ie9以前的版本支持
btns[2].attachEvent('onclick', function() {
alert(11);
})
删除事件
// 2. removeEventListener 删除事件
divs[1].addEventListener('click', fn)
// 里面的fn 不需要调用加小括号
function fn() {
alert(22);
divs[1].removeEventListener('click', fn);
detachEvent
divs[2].attachEvent('onclick', fn1);
function fn1() {
alert(33);
divs[2].detachEvent('onclick', fn1);
}
</script>
DOM事件流
比如我们给一个div 注册了点击事件:
1. 捕获阶段 2. 当前目标阶段 3. 冒泡阶段
事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即 DOM 事件流。
1. JS 代码中只能执行捕获或者冒泡其中的一个阶段。
2. onclick 和 attachEvent 只能得到冒泡阶段。
3. 3. addEventListener(type, listener[, useCapture])第三个参数如果是 true,表示在事件捕 获阶段调用事件处理程序;如果是 false(不写默认就是false),表示在事件冒泡阶段调用事件处理 程序。
4. 4. 实际开发中我们很少使用事件捕获,我们更关注事件冒泡。
5. 5. 有些事件是没有冒泡的,比如 onblur、onfocus、onmouseenter、onmouseleave 6. 事件冒泡有时候会带来麻烦,有时候又会帮助很巧妙的做某些事件,我们后面讲解。
事件对象
官方解释:event 对象代表事件的状态,比如键盘按键的状态、鼠标的位置、鼠标按钮的状态。
简单理解:事件发生后,跟事件相关的一系列信息数据的集合都放到这个对象里面,这个对象就是事件对象 event,它有很多属性和方法。
比如:
1. 谁绑定了这个事件。
2. 鼠标触发事件的话,会得到鼠标的相关信息,如鼠标位置。
3. 键盘触发事件的话,会得到键盘的相关信息,如按了哪个键。
// 1. event 就是一个事件对象 写到我们侦听函数的 小括号里面 当形参来看
// 2. 事件对象只有有了事件才会存在,它是系统给我们自动创建的,不需要我们传递参数
// 3. 事件对象 是 我们事件的一系列相关数据的集合 跟事件相关的
比如鼠标点击里面就包含了鼠标的相关信息,鼠标坐标啊,
如果是键盘事件里面就包含的键盘事件的信息 比如 判断用户按下了那个键
// 4. 这个事件对象我们可以自己命名 比如 event 、 evt、 e
// 5. 事件对象也有兼容性问题 ie678 通过 window.event 兼容性的写法 e = e || window.event;
常见事件对象属性与方法
4.4 事件对象的常见属性和方法
e.target 和 this 的区别: this 是事件绑定的元素, 这个函数的调用者(绑定这个事件的元素)
e.target 是事件触发的元素。
// 常见事件对象的属性和方法
// 1. e.target 返回的是触发事件的对象(元素) this 返回的是绑定事件的对象(元素)
// 区别 : e.target 点击了那个元素,就返回那个元素 this 那个元素绑定了这个点击事件,那么就返回谁
var div = document.querySelector('div');
div.addEventListener('click', function(e) {
console.log(e.target); e.target 返回的是触发事件的对象(元素) 你点了谁就返回谁
console.log(this);
我们给ul 绑定了事件 那么this 就指向ul
点击li 返回的却是ul
var ul = document.querySelector('ul');
ul.addEventListener('click', function(e) {
// 我们给ul 绑定了事件 那么this 就指向ul
console.log(this);
console.log(e.currentTarget);
// e.target 指向我们点击的那个对象 谁触发了这个事件 我们点击的是li e.target 指向的就是li
console.log(e.target);
})
了解兼容性
div.onclick = function(e) {
e = e || window.event;
var target = e.target || e.srcElement;
console.log(target);
}
2. 了解 跟 this 有个非常相似的属性 currentTarget ie678不认识
</script>
事件对象阻止默认行为
// 常见事件对象的属性和方法
// 1. 返回事件类型
var div = document.querySelector('div');
div.addEventListener('click', fn);
div.addEventListener('mouseover', fn);
div.addEventListener('mouseout', fn);
function fn(e) {
console.log(e.type); 返回的是不带on
}
// 2. 阻止默认行为(事件) 让链接不跳转 或者让提交按钮不提交
var a = document.querySelector('a');
a.addEventListener('click', function(e) {
e.preventDefault(); // dom 标准写法
})
/ 3. 传统的注册方式
a.onclick = function(e) {
// 普通浏览器 e.preventDefault(); 方法
// e.preventDefault();
低版本浏览器 ie678 returnValue 属性
e.returnValue; 属性
// 我们可以利用return false 也能阻止默认行为
没有兼容性问题
特点: return 后面的代码不执行了, 而且只限于传统的注册方式
return false;
alert(11); 不会执行
}
</script>
阻止事件冒泡
var son = document.querySelector('.son');
son.addEventListener('click', function(e) {
alert('son');
e.stopPropagation();
// stop 停止 Propagation 传播
低版本浏览器
e.cancelBubble = true;
// 非标准 cancel 取消 bubble 泡泡
}, false);
5.2 阻止事件冒泡的兼容性解决方案
if(e && e.stopPropagation){
e.stopPropagation(); }else{
window.event.cancelBubble = true; }
事件委托!!
<script>
// 事件委托的核心原理:给父节点添加侦听器,
利用事件冒泡影响每一个子节点
var ul = document.querySelector('ul');
ul.addEventListener('click', function(e) {
// alert('知否知否,点我应有弹框在手!');
// e.target 这个可以得到我们点击的对象
e.target.style.backgroundColor = 'pink';
})
</script>
常见鼠标事件(禁止复制文本)
// 1. contextmenu 我们可以禁用右键菜单
document.addEventListener('contextmenu', function(e) {
e.preventDefault();
})
// 2. 禁止选中文字 selectstart
document.addEventListener('selectstart', function(e) {
e.preventDefault();
})
常用的鼠标事件对象
// 鼠标事件对象 MouseEvent
document.addEventListener('click',
function(e) {
// 1. client 鼠标在可视区的x和y坐标
console.log(e.clientX);
console.log(e.clientY);
console.log('---------------------');
不管页面拖不拖动 都以可视窗口 拖动页面不变
// 2. page 鼠标在页面文档的x和y坐标
console.log(e.pageX);
console.log(e.pageY);
console.log('---------------------');
// 3. screen 鼠标在电脑屏幕的x和y坐标
console.log(e.screenX);
console.log(e.screenY);
})
常用的键盘事件
// 常用的键盘事件
1. keyup 按键弹起的时候触发
document.onkeyup = function() {
console.log('我弹起了');
// }
document.addEventListener('keyup', function() {
console.log('我弹起了');
})
//3. keypress 按键按下的时候触发
不能识别功能键 比如 ctrl shift 左右箭头啊
document.addEventListener('keypress', function() {
console.log('我按下了press');
})
//2. keydown 按键按下的时候触发
能识别功能键 比如 ctrl shift 左右箭头啊
document.addEventListener('keydown', function() {
console.log('我按下了down');
})
4. 三个事件的执行顺序 keydown -- keypress -- keyup
</script>
</body>
键盘事件对象之keyCode属性
键盘事件对象中的keyCode属性可以得到相应键的ASCII码值
1. 我们的keyup 和keydown事件不区分字母大小写 a 和 A 得到的都是65
// 2. 我们的keypress 事件 区分字母大小写 a 97 和 A 得到的是65
document.addEventListener('keyup', function(e) {
// console.log(e);
console.log('up:' + e.keyCode);
我们可以利用keycode返回的ASCII码值来判断用户按下了那个键
if (e.keyCode === 65) {
alert('您按下的a键');
} else {
alert('您没有按下a键')
}
})
document.addEventListener('keypress', function(e) {
// console.log(e);
console.log('press:' + e.keyCode);
})
</script>
BOM顶级对象window
BOM
window常见事件onload
// window.onload = function() {
// alert(22);
// }
window.addEventListener('load', function() {
var btn = document.querySelector('button');
btn.addEventListener('click', function() {
alert('点击我');
})
})
window.addEventListener('load', function() {
alert(22);
})
// load 等页面内容全部加载完毕,包含页面dom元素 图片 flash css 等等
// DOMContentLoaded 是DOM 加载完毕,不包含图片 falsh css 等就可以执行 加载速度比 load更快一些
document.addEventListener('DOMContentLoaded', function() {
alert(33);
})
注意:
1. 有了 window.onload 就可以把 JS 代码写到页面元素的上方,因为 onload 是等页面内容全部加载完毕, 再去执行处理函数。
2. window.onload 传统注册事件方式 只能写一次,如果有多个,会以最后一个 window.onload 为准。
3. 如果使用 addEventListener 则没有限制
2.1 窗口加载事件
document.addEventListener('DOMContentLoaded',function(){
})
DOMContentLoaded 事件触发时,仅当DOM加载完成,不包括样式表,图片,flash等等。
Ie9以上才支持 如果页面的图片很多的话,
从用户访问到onload触发可能需要较长的时间, 交互效果就不能实现,必然影响用 户的体验,此时用 DOMContentLoaded 事件比较合适。
调整窗口大小事件
定时器
// 1. setTimeout
// 语法规范: window.setTimeout(调用函数, 延时时间);
// 1. 这个window在调用的时候可以省略
// 2. 这个延时时间单位是毫秒 但是可以省略,如果省略默认的是0
// 3. 这个调用函数可以直接写函数 还可以写 函数名 还有一个写法 '函数名()'
// 4. 页面中可能有很多的定时器,我们经常给定时器加标识符 (名字)
// setTimeout(function() {
// console.log('时间到了');
// }, 2000);
function callback() {
console.log('爆炸了');
}
var timer1 = setTimeout(callback, 3000);
var timer2 = setTimeout(callback, 5000);
// setTimeout('callback()', 3000); // 我们不提倡这个写法
</script>
</body>