1.0 DOM核心总结

关于dom操作,我们主要针对于元素的操作。主要有创建、增、删、改、查、属性操作、事件操作。

1.1创建

  1. document.write()
  2. element.innerHTML
  3. document.createElement()
  1. document.write //是直接将内容写入页面的内容流,界面加载完成之后,再写入,这样它会导致页面全部重绘
  2. innerHTML //是将内容写入某个 DOM 节点,不会导致页面全部重绘
  3. innerHTML //创建多个元素效率更高(不要拼接字符串,采取数组形式拼接),结构稍微复杂
  4. createElement() //创建多个元素效率稍低一点点,但是结构更清晰
  5. 总结:不同浏览器下,innerHTML 效率要比 creatElement

案例:

  1. <script>
  2. // 三种创建元素方式区别
  3. // 1. document.write() 创建元素 如果页面文档流加载完毕,再调用这句话会导致页面重绘
  4. var btn = document.querySelector('button');
  5. btn.onclick = function() {
  6. document.write('<div>123</div>');
  7. }
  8. // 2. innerHTML 创建元素
  9. var inner = document.querySelector('.inner');
  10. for (var i = 0; i <= 100; i++) {
  11. inner.innerHTML += '<a href="#">百度</a>'
  12. }
  13. var arr = [];
  14. for (var i = 0; i <= 100; i++) {
  15. arr.push('<a href="#">百度</a>');
  16. }
  17. inner.innerHTML = arr.join('');
  18. // 3. document.createElement() 创建元素
  19. var create = document.querySelector('.create');
  20. for (var i = 0; i <= 100; i++) {
  21. var a = document.createElement('a');
  22. create.appendChild(a);
  23. }
  24. </script>
  • innerHTML字符串拼接方式(效率低)
  1. <script>
  2. function fn() {
  3. var d1 = +new Date();
  4. var str = '';
  5. for (var i = 0; i < 1000; i++) {
  6. document.body.innerHTML += '<div style="width:100px; height:2px; border:1px solid blue;"></div>';
  7. }
  8. var d2 = +new Date();
  9. console.log(d2 - d1);
  10. }
  11. fn();
  12. </script>
  1. 总结:因为要多次开辟变量空间,所以效率低
  • createElement方式(效率一般,但结构清晰)
  1. <script>
  2. function fn() {
  3. var d1 = +new Date();
  4. for (var i = 0; i < 1000; i++) {
  5. var div = document.createElement('div');
  6. div.style.width = '100px';
  7. div.style.height = '2px';
  8. div.style.border = '1px solid red';
  9. document.body.appendChild(div);
  10. }
  11. var d2 = +new Date();
  12. console.log(d2 - d1);
  13. }
  14. fn();
  15. </script>
  • innerHTML数组方式(效率高)
  1. <script>
  2. function fn() {
  3. var d1 = +new Date();
  4. var array = [];
  5. for (var i = 0; i < 1000; i++) {
  6. array.push('<div style="width:100px; height:2px; border:1px solid blue;"></div>');
  7. }
  8. document.body.innerHTML = array.join('');
  9. var d2 = +new Date();
  10. console.log(d2 - d1);
  11. }
  12. fn();
  13. </script>

1.2增加

  1. appendChild
  2. insertBefore
  1. 1. 末尾添加:element.appendChild(childNode)
  2. childNode 添加到element的子节点列表的末尾
  3. 2. 指定位置添加:element.insertBefore(childNode, 指定元素)
  4. childNode 添加到element的指定元素的前面
  5. 如:
  6. ul.appendChild(li);
  7. ul.insertBefore(li2, ul.children[0]);

1.3删

1、removeChild

  1. node.removeChild(child)
  2. 如:
  3. ul.removeChild(ul.children[0]);

1.4改

  1. 修改元素属性: src、href、title等
  2. 修改普通元素内容: innerHTML 、innerText
  3. 修改表单元素: value、type、disabled等
  4. 修改元素样式: style、className

1.5查

  1. DOM提供的API 方法: getElementById、getElementsByTagName
  2. H5提供的新方法: querySelector、querySelectorAll
  3. 利用节点操作获取元素: 父(parentNode)、子(children)、兄(previousElementSibling、nextElementSibling)

1.6属性操作

主要针对于自定义属性:

  1. setAttribute:设置dom的属性值element.setAttribute(‘data-index’, 2)
  2. getAttribute:得到dom的属性值element.getAttribute(‘data-index’);
  3. removeAttribute移除属性node.removeChild(child)

2.0事件高级

2.1注册事件(2种方式)

给元素添加事件,称为注册事件或者绑定事件。

  • 传统方式
    注意:同一个元素同一个事件只能设置一个处理函数,最后注册的处理函数将会覆盖前面注册的处理函数

    1. 利用 on 开头的事件 onclick
    2. <button onclick=“alert('~~~~hi~~~~~')”></button>
    3. btn.onclick = function() {}
  • 方法监听

    • addEventListener() : 添加事件监听//有兼容
    • 特点:同一个元素同一个事件可以注册多个监听器(事件处理程序)
    • 按注册顺序依次执行
      1. // 参数1:事件类型,它是字符串 必定加引号 而且不带on
      2. // 参数2:事件处理程序
      3. btns[1].addEventListener('click', function() {
      4. alert(22);
      5. })
      6. btns[1].addEventListener('click', function() {
      7. alert(33);
      8. })
      9. // 3. attachEvent ie9以前的版本支持 ,这里的事件需要带on
      10. btns[2].attachEvent('onclick', function() {
      11. alert(11);
      12. })

2.2 事件监听

  1. addEventListener事件监听 //有兼容
  2. eventTarget.addEventListener(type, listener[, useCapture])
  3. 该方法接收三个参数:
  4. 1. type:事件类型**字符串**,比如 click mouseover ,注意这里不要带 on
  5. 2. listener:事件处理函数,事件发生时,会调用该监听函数
  6. 3. useCapture:可选参数,是一个布尔值,默认是 false

2.3attacheEvent()事件监听

  1. eventTarget.attachEvent(eventNameWithOn, callback) //有兼容

2.4事件监听兼容性解决方案

  1. function addEventListener(element, eventName, fn) {
  2. // 判断当前浏览器是否支持 addEventListener 方法
  3. if (element.addEventListener) { // 浏览器支持此种方式,可以根据方法名找到方法声明,方法声明会转换为true
  4. element.addEventListener(eventName, fn); // 第三个参数 默认是false
  5. } else if (element.attachEvent) {
  6. element.attachEvent('on' + eventName, fn);
  7. } else {
  8. // 相当于 element.onclick = fn;
  9. element['on' + eventName] = fn;
  10. }

2.5删除事件(解绑事件)

传统方式

  1. eventTarget.onclick = null;

方法监听注册方式

  1. 1. eventTarget.removeEventListener(type, listener[, useCapture]);
  2. 2. eventTarget.detachEvent(eventNameWithOn, callback);
  1. <div>1</div>
  2. <div>2</div>
  3. <div>3</div>
  4. <script>
  5. var divs = document.querySelectorAll('div');
  6. divs[0].onclick = function() {
  7. alert(11);
  8. // 1. 传统方式删除事件
  9. divs[0].onclick = null;
  10. }
  11. // 2. removeEventListener 删除事件
  12. divs[1].addEventListener('click', fn) // 里面的fn 不需要调用加小括号
  13. function fn() {
  14. alert(22);
  15. // 点击div1的时候弹出22,然后直接移除点击事件。
  16. // 移除事件需要参数1,哪种事件,参数2,这种事件中的fn处理程序
  17. // 为啥需要指定处理程序fn?因为这个点击事件可以有多个处理程序,你要指定删除哪个
  18. divs[1].removeEventListener('click', fn);
  19. // divs[1].addEventListener('click', fn()) // 里面的fn 不需要调用加小括号
  20. // 如果添加了小括号,就相当于将fn()调用完成的返回值作为第二个参数传递了
  21. // 事件处理程序,不是我们调用的,而是js引擎调用的。
  22. // 我们通过第二个参数,告诉js引擎,事件发生时要调用的方法是谁,所以只告诉他方面即可
  23. }
  24. // 3. detachEvent
  25. divs[2].attachEvent('onclick', fn1);
  26. function fn1() {
  27. alert(33);
  28. divs[2].detachEvent('onclick', fn1);
  29. }
  30. </script>

2.6删除事件兼容性解决方案

  1. function removeEventListener(element, eventName, fn) {
  2. // 判断当前浏览器是否支持 removeEventListener 方法
  3. if (element.removeEventListener) {
  4. element.removeEventListener(eventName, fn); // 第三个参数 默认是false
  5. } else if (element.detachEvent) {
  6. element.detachEvent('on' + eventName, fn);
  7. } else {
  8. element['on' + eventName] = null;
  9. }

3.0 DOM事件流

3.1 DOM 事件流会经历3个阶段:

  1. 捕获阶段
  2. 当前目标阶段
  3. 冒泡阶段

我们向水里面扔一块石头,首先它会有一个下降的过程,这个过程就可以理解为从最顶层向事件发生的最具体元素(目标点)的捕获过程;之后会产生泡泡,会在最低点( 最具体元素)之后漂浮到水面上,这个过程相当于事件冒泡。

案例

  1. <div class="father">
  2. <div class="son">son盒子</div>
  3. </div>
  4. <script>
  5. // 如果addEventListener 第三个参数是 true 那么则处于捕获阶段
  6. // 顺序为:document -> html -> body -> father -> son
  7. // 如果addEventListener 第三个参数是 false 或者 省略 那么处理冒泡阶段
  8. // 顺序为:son -> father ->body -> html -> document
  9. var son = document.querySelector('.son');
  10. // 给son注册单击事件
  11. son.addEventListener('click', function() {
  12. alert('son');
  13. }, false);
  14. // 给father注册单击事件
  15. var father = document.querySelector('.father');
  16. father.addEventListener('click', function() {
  17. alert('father');
  18. }, false);
  19. // 给document注册单击事件,省略第3个参数
  20. document.addEventListener('click', function() {
  21. alert('document');
  22. })
  23. </script>
  1. 有些事件是没有冒泡的,比如 onblur、onfocus、onmouseenter、onmouseleave
  2. addEventListener(type, listener[, useCapture])第三个参数如果是 true,表示在事件捕获阶段调用事件处理程序;如果是 false(不写默认就是false),表示在事件冒泡阶段调用事件处理程序。
  3. onclick 和 attachEvent 只能得到冒泡阶段。

3.2 事件对象

  1. 谁绑定了这个事件。
  2. 鼠标触发事件的话,会得到鼠标的相关信息,如鼠标位置。
  3. 键盘触发事件的话,会得到键盘的相关信息,如按了哪个键。
  1. 通常情况下target this是一致的
  2. 但有一种情况不同,那就是在事件冒泡时(父子元素有相同事件,单击子元素,父元素的事件处理函数也会被触发执行),
  3. 这时候this指向的是父元素,因为它是绑定事件的元素对象,
  4. target指向的是子元素,因为他是触发事件的那个具体元素对象。
  5. 总结
  6. e.target 点击了哪个元素,就返回哪个元素
  7. 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禁止鼠标右键

  1. document.addEventListener('contextmenu', function(e) {
  2. e.preventDefault();
  3. })
  1. document.addEventListener('selectstart', function(e) {
  2. e.preventDefault();
  3. })

3.8常用鼠标事件

  • 禁止选中文字
    • selectstart 事件:鼠标选中事件,用于界面文字防止选中
  • 禁止右键菜单
    • contextmenu事件:鼠标右键菜单事件。主要控制应该何时显示上下文菜单(右键菜单),主要用于程序员取消默认的上下文菜单
  • 鼠标事件对象

clientX 和 clientY 鼠标在可视区域的X、Y坐标

pageX 和 pageY 相当于文档页面的X、Y坐标

screenX 和 screenY 相当于电脑屏幕的X、Y坐标

  1. // 1. client 鼠标在可视区的x和y坐标
  2. console.log(e.clientX);
  3. console.log(e.clientY);
  4. console.log('---------------------');
  5. // 2. page 鼠标在页面文档的x和y坐标
  6. console.log(e.pageX);
  7. console.log(e.pageY);
  8. console.log('---------------------');
  9. // 3. screen 鼠标在电脑屏幕的x和y坐标
  10. console.log(e.screenX);
  11. console.log(e.screenY);

4.0常用的键盘事件

4.1 键盘事件

  • 事件:
    • onkeyup:某个键盘按键被松开时触发
    • onkeydown:某个键盘按键被按下时触发
    • onkeypress:某个键盘按键被按下时触发(但它不识别功能键,比如 Ctrl shift 箭头等)
    • 三个事件的执行顺序:keydown —- keypress —- keyup (按下 —- 按住 —- 抬起)

4.2 键盘事件对象

  • 键盘事件对象中的keyCode属性可以得到相应键的ASCII码值
  1. onkeydown 和 onkeyup 不区分字母大小写,通过keyCode属性获取到的a 和 A 得到的都是65
  2. onkeypress 区分字母大小写 ,通过keyCode属性获取到的 a 是 97 和 A 得到的是65
  3. keydown和keyup, 它能识别所有的键(包括功能键)
  4. Keypress 不识别功能键,但是keyCode属性能区分大小写,返回不同的ASCII值