1.0 DOM核心总结
关于dom操作,我们主要针对于元素的操作。主要有创建、增、删、改、查、属性操作、事件操作。
1.1创建
- document.write()
- element.innerHTML
- document.createElement()
document.write //是直接将内容写入页面的内容流,界面加载完成之后,再写入,这样它会导致页面全部重绘innerHTML //是将内容写入某个 DOM 节点,不会导致页面全部重绘innerHTML //创建多个元素效率更高(不要拼接字符串,采取数组形式拼接),结构稍微复杂createElement() //创建多个元素效率稍低一点点,但是结构更清晰总结:不同浏览器下,innerHTML 效率要比 creatElement 高
案例:
<script>// 三种创建元素方式区别// 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('');// 3. document.createElement() 创建元素var create = document.querySelector('.create');for (var i = 0; i <= 100; i++) {var a = document.createElement('a');create.appendChild(a);}</script>
- innerHTML字符串拼接方式(效率低)
<script>function fn() {var d1 = +new Date();var str = '';for (var i = 0; i < 1000; i++) {document.body.innerHTML += '<div style="width:100px; height:2px; border:1px solid blue;"></div>';}var d2 = +new Date();console.log(d2 - d1);}fn();</script>
总结:因为要多次开辟变量空间,所以效率低
- createElement方式(效率一般,但结构清晰)
<script>function fn() {var d1 = +new Date();for (var i = 0; i < 1000; i++) {var div = document.createElement('div');div.style.width = '100px';div.style.height = '2px';div.style.border = '1px solid red';document.body.appendChild(div);}var d2 = +new Date();console.log(d2 - d1);}fn();</script>
- innerHTML数组方式(效率高)
<script>function fn() {var d1 = +new Date();var array = [];for (var i = 0; i < 1000; i++) {array.push('<div style="width:100px; height:2px; border:1px solid blue;"></div>');}document.body.innerHTML = array.join('');var d2 = +new Date();console.log(d2 - d1);}fn();</script>
1.2增加
- appendChild
- insertBefore
1. 末尾添加:element.appendChild(childNode)将 childNode 添加到element的子节点列表的末尾2. 指定位置添加:element.insertBefore(childNode, 指定元素)将childNode 添加到element的指定元素的前面如:ul.appendChild(li);ul.insertBefore(li2, ul.children[0]);
1.3删
1、removeChild
node.removeChild(child)如:ul.removeChild(ul.children[0]);
1.4改
- 修改元素属性: src、href、title等
- 修改普通元素内容: innerHTML 、innerText
- 修改表单元素: value、type、disabled等
- 修改元素样式: style、className
1.5查
- DOM提供的API 方法: getElementById、getElementsByTagName
- H5提供的新方法: querySelector、querySelectorAll
- 利用节点操作获取元素: 父(parentNode)、子(children)、兄(previousElementSibling、nextElementSibling)
1.6属性操作
主要针对于自定义属性:
- setAttribute:设置dom的属性值element.setAttribute(‘data-index’, 2)
- getAttribute:得到dom的属性值element.getAttribute(‘data-index’);
- removeAttribute移除属性node.removeChild(child)
2.0事件高级
2.1注册事件(2种方式)
给元素添加事件,称为注册事件或者绑定事件。
传统方式
注意:同一个元素同一个事件只能设置一个处理函数,最后注册的处理函数将会覆盖前面注册的处理函数利用 on 开头的事件 onclick<button onclick=“alert('~~~~hi~~~~~')”></button>btn.onclick = function() {}
方法监听
- addEventListener() : 添加事件监听//有兼容
- 特点:同一个元素同一个事件可以注册多个监听器(事件处理程序)
- 按注册顺序依次执行
// 参数1:事件类型,它是字符串 必定加引号 而且不带on// 参数2:事件处理程序btns[1].addEventListener('click', function() {alert(22);})btns[1].addEventListener('click', function() {alert(33);})// 3. attachEvent ie9以前的版本支持 ,这里的事件需要带onbtns[2].attachEvent('onclick', function() {alert(11);})
2.2 事件监听
addEventListener事件监听 //有兼容eventTarget.addEventListener(type, listener[, useCapture])该方法接收三个参数:1. type:事件类型**字符串**,比如 click 、mouseover ,注意这里不要带 on2. listener:事件处理函数,事件发生时,会调用该监听函数3. useCapture:可选参数,是一个布尔值,默认是 false。
2.3attacheEvent()事件监听
eventTarget.attachEvent(eventNameWithOn, callback) //有兼容
2.4事件监听兼容性解决方案
function addEventListener(element, eventName, fn) {// 判断当前浏览器是否支持 addEventListener 方法if (element.addEventListener) { // 浏览器支持此种方式,可以根据方法名找到方法声明,方法声明会转换为trueelement.addEventListener(eventName, fn); // 第三个参数 默认是false} else if (element.attachEvent) {element.attachEvent('on' + eventName, fn);} else {// 相当于 element.onclick = fn;element['on' + eventName] = fn;}
2.5删除事件(解绑事件)
传统方式
eventTarget.onclick = null;
方法监听注册方式
1. eventTarget.removeEventListener(type, listener[, useCapture]);2. eventTarget.detachEvent(eventNameWithOn, callback);
<div>1</div><div>2</div><div>3</div><script>var divs = document.querySelectorAll('div');divs[0].onclick = function() {alert(11);// 1. 传统方式删除事件divs[0].onclick = null;}// 2. removeEventListener 删除事件divs[1].addEventListener('click', fn) // 里面的fn 不需要调用加小括号function fn() {alert(22);// 点击div1的时候弹出22,然后直接移除点击事件。// 移除事件需要参数1,哪种事件,参数2,这种事件中的fn处理程序// 为啥需要指定处理程序fn?因为这个点击事件可以有多个处理程序,你要指定删除哪个divs[1].removeEventListener('click', fn);// divs[1].addEventListener('click', fn()) // 里面的fn 不需要调用加小括号// 如果添加了小括号,就相当于将fn()调用完成的返回值作为第二个参数传递了// 事件处理程序,不是我们调用的,而是js引擎调用的。// 我们通过第二个参数,告诉js引擎,事件发生时要调用的方法是谁,所以只告诉他方面即可}// 3. detachEventdivs[2].attachEvent('onclick', fn1);function fn1() {alert(33);divs[2].detachEvent('onclick', fn1);}</script>
2.6删除事件兼容性解决方案
function removeEventListener(element, eventName, fn) {// 判断当前浏览器是否支持 removeEventListener 方法if (element.removeEventListener) {element.removeEventListener(eventName, fn); // 第三个参数 默认是false} else if (element.detachEvent) {element.detachEvent('on' + eventName, fn);} else {element['on' + eventName] = null;}
3.0 DOM事件流
3.1 DOM 事件流会经历3个阶段:
- 捕获阶段
- 当前目标阶段
- 冒泡阶段
我们向水里面扔一块石头,首先它会有一个下降的过程,这个过程就可以理解为从最顶层向事件发生的最具体元素(目标点)的捕获过程;之后会产生泡泡,会在最低点( 最具体元素)之后漂浮到水面上,这个过程相当于事件冒泡。
案例
<div class="father"><div class="son">son盒子</div></div><script>// 如果addEventListener 第三个参数是 true 那么则处于捕获阶段// 顺序为:document -> html -> body -> father -> son// 如果addEventListener 第三个参数是 false 或者 省略 那么处理冒泡阶段// 顺序为:son -> father ->body -> html -> documentvar son = document.querySelector('.son');// 给son注册单击事件son.addEventListener('click', function() {alert('son');}, false);// 给father注册单击事件var father = document.querySelector('.father');father.addEventListener('click', function() {alert('father');}, false);// 给document注册单击事件,省略第3个参数document.addEventListener('click', function() {alert('document');})</script>
- 有些事件是没有冒泡的,比如 onblur、onfocus、onmouseenter、onmouseleave
- addEventListener(type, listener[, useCapture])第三个参数如果是 true,表示在事件捕获阶段调用事件处理程序;如果是 false(不写默认就是false),表示在事件冒泡阶段调用事件处理程序。
- onclick 和 attachEvent 只能得到冒泡阶段。
3.2 事件对象
- 谁绑定了这个事件。
- 鼠标触发事件的话,会得到鼠标的相关信息,如鼠标位置。
- 键盘触发事件的话,会得到键盘的相关信息,如按了哪个键。
通常情况下target 和 this是一致的但有一种情况不同,那就是在事件冒泡时(父子元素有相同事件,单击子元素,父元素的事件处理函数也会被触发执行),这时候this指向的是父元素,因为它是绑定事件的元素对象,而target指向的是子元素,因为他是触发事件的那个具体元素对象。总结 :e.target 点击了哪个元素,就返回哪个元素this 哪个元素绑定了这个点击事件,那么就返回谁
3.3 事件冒泡:
事件传播的过程叫做DOM事件流
捕获阶段 当前目标阶段 冒泡阶段
事件捕获是从外到里 事件冒泡是从里到外
3.4事件委托
- 原理:不是每个子节点单独设置事件监听器,而是事件监听器设置在其父节点上,然后利用冒泡原理影响设置每个子节点。
- 例:给 ul 注册点击事件,然后利用事件对象的 target 来找到当前点击的 li,因为点击 li,事件会冒泡到 ul 上, ul 有注册事件,就会触发事件监听器。
3.5阻止默认行为
e.preventDefault(); 方法 但是有兼容性问题 ie9以上才支持
e.returnValue;属性 专门针对ie低版本的
return false //特点 return后面的代码就不执行了 只限于传统的注册方式
3.6阻止冒泡效果:
e.stopPropagation
window.event.setPropagation
window.e.cancelBubble=true//没有兼容性问题
3.7禁止鼠标右键
document.addEventListener('contextmenu', function(e) {e.preventDefault();})
document.addEventListener('selectstart', function(e) {e.preventDefault();})
3.8常用鼠标事件
- 禁止选中文字
- selectstart 事件:鼠标选中事件,用于界面文字防止选中
- 禁止右键菜单
- contextmenu事件:鼠标右键菜单事件。主要控制应该何时显示上下文菜单(右键菜单),主要用于程序员取消默认的上下文菜单
- 鼠标事件对象
clientX 和 clientY 鼠标在可视区域的X、Y坐标
pageX 和 pageY 相当于文档页面的X、Y坐标
screenX 和 screenY 相当于电脑屏幕的X、Y坐标
// 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);
4.0常用的键盘事件
4.1 键盘事件
- 事件:
- onkeyup:某个键盘按键被松开时触发
- onkeydown:某个键盘按键被按下时触发
- onkeypress:某个键盘按键被按下时触发(但它不识别功能键,比如 Ctrl shift 箭头等)
- 三个事件的执行顺序:keydown —- keypress —- keyup (按下 —- 按住 —- 抬起)
4.2 键盘事件对象
- 键盘事件对象中的keyCode属性可以得到相应键的ASCII码值
- onkeydown 和 onkeyup 不区分字母大小写,通过keyCode属性获取到的a 和 A 得到的都是65
- onkeypress 区分字母大小写 ,通过keyCode属性获取到的 a 是 97 和 A 得到的是65
- keydown和keyup, 它能识别所有的键(包括功能键)
- Keypress 不识别功能键,但是keyCode属性能区分大小写,返回不同的ASCII值
