1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title></title>
  8. <style>
  9. div {
  10. width: 100px;
  11. height: 100px;
  12. background-color: green;
  13. }
  14. </style>
  15. </head>
  16. <body>
  17. <div></div>
  18. <script>
  19. //事件
  20. //吃饭
  21. // onclick = function () {//事件反馈}
  22. //绑定事件处理程序 事件处理函数
  23. //绑定事件=绑定事件的处理函数
  24. /*点击,鼠标移入移出,这是天生就有的能力,有默认值,
  25. 添加的是发生事件的反馈*/
  26. var oDiv = document.getElementsByTagName('div')[0];
  27. /*句柄,onclick句柄,onclick=function() {}事件句柄,
  28. 事件句柄的绑定方式,事件句柄绑定在哪个元素上,哪个元素
  29. 就是事件源*/
  30. oDiv.onclick = function () {
  31. this.style.backgroundColor = 'orange';
  32. }
  33. //事件+事件的反馈=前端交互 交互体验
  34. //这是前端的核心价值
  35. //如何绑定事件处理函数
  36. // elem.onclick = function() {
  37. // }
  38. </script>
  39. </body>
  40. </html>

image.png

每个元素都有点击事件,点击方法,点击的反馈默认没有,绑定的是事件的反馈,绑定的是当点击事件发生时,会产生的效果。
前端的核心是交互,用户点击,产生变化,用户看见变化。
image.png
触发两个事件

image.png
触发一个事件,因为一个方法,指向一个空间

image.png
image.png

绑定事件处理函数on

写法一

  1. obj.onclick = functin(){
  2. }
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title></title>
  8. <style>
  9. button{
  10. outline: none;
  11. }
  12. .loading{
  13. background-color: #ddd;
  14. color: #fff;
  15. }
  16. </style>
  17. </head>
  18. <body>
  19. <button>加载更多</button>
  20. <button onclick="console.log(1)">加载更多</button>
  21. /*内联事件监听器,这样写不好,事件与逻辑分开,模块化不能这么写*/
  22. <script>
  23. var oBtn=document.getElementsByTagName('button')[0];
  24. oBtn.onclick = function() {
  25. this.innerHTML = "加载中...";
  26. this.className = "loading";
  27. var self=this;//
  28. setTimeout(function() {
  29. console.log(1);
  30. console.log(this)//window,函数调用指向window
  31. self.innerHTML = "加载更多";
  32. self.className='';
  33. },2000)
  34. }
  35. // oBtn.onclick = function() {
  36. // console.log('加载更多数据');
  37. // }
  38. /* 只能绑定一个函数,兼容性好*/
  39. </script>
  40. </body>
  41. </html>

写法二

  1. obj.onclick = fn;
  2. function fn(){
  3. 内容
  4. }

写法三 :当函数fn有参数的情况下使用匿名函数来传参

  1. obj.onclick = function(){fn(param)};
  2. function fn(param){
  3. //内容
  4. }

行内事件监听器

  1. <button onclick="test()">加载更多</button>

缺点:无法在同一个元素上绑定多个处理函数 后面的绑定函数会覆盖前面的绑定函数

  1. <style>
  2. .loading{
  3. background-color: cadetblue;
  4. }
  5. </style>
  6. </head>
  7. <body>
  8. <button>加载更多</button>
  9. </body>
  10. <script>
  11. var oBtn = document.getElementsByTagName('button')[0];
  12. oBtn.onclick = function(){
  13. this.innerHTML = '加载中....';
  14. this.className = 'loading';
  15. var self = this;
  16. setTimeout(function(){
  17. console.log(1);
  18. self.innerHTML = '加载更多';
  19. self.className = '';
  20. },2000);
  21. }
  22. oBtn.onclick = function(){
  23. console.log('加载更多数据'); //只会打印此处函数
  24. }
  25. </script>

句柄的方式,因为onclick赋予新的看见地址,覆盖了前面的
不能同一个事件绑定多个函数

addEventListener

事件 函数名 是否捕获
addEventListener(event,funtionName,useCapture)

w3c规范,ie9以下不支持

写法一

  1. obj.addEventListener("click",function(){
  2. //do something
  3. }));

写法二 没参数可以直接写函数名

  1. obj.addEventListener("click",fn,fasle));
  2. function fn(){
  3. //do something..
  4. }

写法三 函数有参数时需要使用匿名函数来传递参数

  1. obj.addEventListener("click",function(){fn(parm)},false);

优点:可以绑定多个事件处理函数 W3C规范

缺点:IE9不兼容,

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. <style>
  9. .loading{
  10. background-color: cadetblue;
  11. }
  12. </style>
  13. </head>
  14. <body>
  15. <button>加载更多</button>
  16. </body>
  17. <script>
  18. var oBtn = document.getElementsByTagName('button')[0];
  19. oBtn.addEventListener('click',function(){
  20. this.innerHTML = '加载中....';
  21. this.className = 'loading';
  22. var self = this;
  23. setTimeout(function(){
  24. self.innerHTML = '加载更多';
  25. self.className = '';
  26. },2000);
  27. },false)
  28. oBtn.addEventListener('click',function () {
  29. console.log('加载更多数据');
  30. },false)
  31. </script>
  32. </html>

image.png
打印2次,如果是绑定2次一个方法,只打印1次,与attachEvent这点不一样

IE8及以下的绑定方法

attachEvent(事件类型,事件处理函数)

此函数的内部的this指向window

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. <style>
  9. .loading{
  10. background-color: cadetblue;
  11. }
  12. </style>
  13. </head>
  14. <body>
  15. <button>加载更多</button>
  16. </body>
  17. <script>
  18. var oBtn = document.getElementsByTagName('button')[0];
  19. oBtn.attachEvent('click',function(){
  20. this.innerHTML = '加载中....';
  21. this.className = 'loading';
  22. var self = this;
  23. setTimeout(function(){
  24. self.innerHTML = '加载更多';
  25. self.className = '';
  26. },2000);
  27. })
  28. oBtn.attachEvent('click',function () {
  29. console.log('加载更多数据');
  30. })
  31. </script>
  32. </html>

image.png

即使是一个方法,绑定2次也打印2次

解决闭包点击问题

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. <style>
  9. .loading{
  10. background-color: cadetblue;
  11. }
  12. </style>
  13. </head>
  14. <body>
  15. <ul>
  16. <li>1</li>
  17. <li>2</li>
  18. <li>3</li>
  19. <li>4</li>
  20. <li>5</li>
  21. </ul>
  22. </body>
  23. <script>
  24. var oLi = document.getElementsByTagName('li'),
  25. len = oLi.length,
  26. item;
  27. for(var i= 0;i<len;i++){
  28. (function (i) {
  29. item = oLi[i];
  30. item.addEventListener('click',function(){
  31. console.log(i)
  32. },false)
  33. }(i));
  34. }
  35. </script>
  36. </html>

image.png

封装addEvent方法(兼容IE的绑定事件方法)

image.png

  1. var oBtn = document.getElementsByTagName('button')[0];
  2. addEvent(oBtn,'click',function(){
  3. console.log(1);
  4. });
  5. function addEvent(el,type,fn){
  6. console.log(el);
  7. if(el.addEventListener){
  8. el.addEventListener(type,fn,false);
  9. }else if(el.attachEvent){
  10. el.attachEvent('on'+type,function(){
  11. fn.call(el); //将this指向改为调用的本身
  12. });
  13. }else{
  14. el['on'+type] = fn;
  15. }
  16. }
  1. var oBtn = document.getElementsByTagName('button')[0];
  2. addEvent(oBtn,'click',function(){
  3. console.log(1);
  4. });
  5. //元素,事件类型,触发的方法
  6. function addEvent(el,type,fn){
  7. console.log(el);
  8. if(el.addEventListener){
  9. //方法存在
  10. el.addEventListener(type,fn,false);
  11. }else if(el.attachEvent){
  12. el.attachEvent('on'+type,function(){
  13. fn.call(el); //将this指向改为调用的本身
  14. });
  15. }else{
  16. el['on'+type] = fn;//相当于el.on,例子el.onclick=func
  17. }
  18. }

demo

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. <style>
  9. .loading{
  10. background-color: cadetblue;
  11. }
  12. </style>
  13. </head>
  14. <body>
  15. <ul>
  16. <li>1</li>
  17. <li>2</li>
  18. <li>3</li>
  19. <li>4</li>
  20. <li>5</li>
  21. </ul>
  22. <button>加载更多</button>
  23. </body>
  24. <script>
  25. var oBtn = document.getElementsByTagName('button')[0];
  26. addEvent(oBtn,'click',function(){
  27. console.log(1);
  28. });
  29. function addEvent(el,type,fn){
  30. console.log(el);
  31. if(el.addEventListener){
  32. el.addEventListener(type,fn,false);
  33. }else if(el.attachEvent){
  34. el.attachEvent('on'+type,function(){
  35. fn.call(el); //将this指向改为调用的本身
  36. });
  37. }else{
  38. el['on'+type] = fn;
  39. }
  40. }
  41. </script>
  42. </html>

移除事件处理函数的方法

  1. element.onclick = null/fasle//取消点击方法
  2. element.addEventListener('click',test,false); //参数与下方remove一一对应
  3. element.removeEventListener('click',test,false);
  4. IE的方法
  5. elment.attachEvent('onclick',test);
  6. elment.detachEvent('onclick',test);//方法参数不一样
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title></title>
  8. <style>
  9. button{
  10. outline: none;
  11. border: none;
  12. width: 100px;
  13. height: 30px;
  14. background-color: red;
  15. color: #fff;
  16. }
  17. .got{
  18. background-color: #ddd;
  19. }
  20. </style>
  21. </head>
  22. <body>
  23. <button>领取优惠券</button>
  24. <script>
  25. var oBtn=document.getElementsByTagName('button')[0];
  26. //移除
  27. oBtn.onclick = function() {
  28. this.className='got';
  29. this.innerHTML = "已领取";
  30. this.onclick=null;
  31. }
  32. //移除1
  33. oBtn.addEventListener('click',test,false);
  34. function test() {
  35. this.className = 'got';
  36. this.innerHTML = '以领取';
  37. this.removeEventListener('click',test,false);
  38. }
  39. oBtn.attachEvent("onclick",test)
  40. oBtn.detachEvent("onclick",test)
  41. //移除2
  42. oBtn.addEventListener('click',function test() {
  43. this.className = 'got';
  44. this.innerHTML = '以领取';
  45. this.removeEventListener('click',test,false);
  46. })
  47. //移除3
  48. oBtn.addEventListener('click',function() {
  49. this.className = 'got';
  50. this.innerHTML = '以领取';
  51. console.log(arguments.callee)
  52. this.removeEventListener('click',arguments.callee,false);//得到匿名函数
  53. })
  54. </script>
  55. </body>
  56. </html>

image.png

image.png
一一对应的

image.png
image.png

封装removeEvent删除事件处理函数

  1. //移除事件
  2. function removeEvent(elem,type,fn){
  3. if(elem.addEventListener){
  4. elem.removeEventListener(type,fn,false);
  5. }else if(elem.attachEvent){
  6. elem.detachEvent('on'+type,fn);
  7. }else{
  8. elem['on'+type] = null
  9. }
  10. }

使用场景 优惠券领取后不可再领取 this.onclick = null;
demo

  1. //写法一:
  2. var oBtn = document.getElementsByTagName('button')[0];
  3. oBtn.onclick = function(){
  4. this.className = 'got';
  5. this.innerHTML = '已领取';
  6. this.onclick = null; //**********
  7. }
  8. //写法二:
  9. var oBtn = document.getElementsByTagName('button')[0];
  10. oBtn.addEventListener('click',test,false);
  11. function test(){
  12. this.className = 'got';
  13. this.innerHTML = '已领取';
  14. this.removeEventListener('click',test,false);
  15. }
  16. //写法三
  17. var oBtn = document.getElementsByTagName('button')[0];
  18. oBtn.addEventListener('click',function test(){
  19. this.className = 'got';
  20. this.innerHTML = '已领取';
  21. this.removeEventListener('click',test,false);
  22. },false);
  23. //写法四非严格模式下 arguments.callee
  24. var oBtn = document.getElementsByTagName('button')[0];
  25. oBtn.addEventListener('click',function(){
  26. this.className = 'got';
  27. this.innerHTML = '已领取';
  28. this.removeEventListener('click',arguments.callee,false);
  29. },false);

HTML 小记
a标签不能嵌套a标签 嵌套了会自动分开

事件冒泡与捕获

true事件捕获 ,父向子元素传递,父元素指向事件源,到事件源停止
false事件冒泡,子元素向父元素方向传递,传递子元素的事件并且触发父元素的事件
事件源:点击的元素
从里面向外面传递,向body元素的方向,只要是元素逻辑就行

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. <style>
  9. .wrapper{
  10. display: block;
  11. width: 300px;
  12. height: 300px;
  13. background-color: green;
  14. }
  15. .outer{
  16. display: block;
  17. width: 200px;
  18. height: 200px;
  19. background-color: red;
  20. }
  21. .inner{
  22. display: block;
  23. width: 100px;
  24. height: 100px;
  25. background-color: orange;
  26. }
  27. </style>
  28. </head>
  29. <body>
  30. <div class="wrapper">
  31. <div class="outer">
  32. <div class="inner">inner</div>
  33. outer
  34. </div>
  35. wrapper
  36. </div>
  37. </body>
  38. <script>
  39. var wrapper = document.getElementsByClassName('wrapper')[0],
  40. outer = wrapper.getElementsByClassName('outer')[0],
  41. inner = outer.getElementsByClassName('inner')[0];
  42. wrapper.addEventListener('click',function(){
  43. console.log('wrapper-f');
  44. },false);
  45. outer.addEventListener('click',function(){
  46. console.log('outer-f');
  47. },false);
  48. inner.addEventListener('click',function(){
  49. console.log('inner-f');
  50. },false);
  51. wrapper.addEventListener('click',function(){
  52. console.log('wrapper-t');
  53. },true);
  54. outer.addEventListener('click',function(){
  55. console.log('outer-t');
  56. },true);
  57. inner.addEventListener('click',function(){
  58. console.log('inner-t');
  59. },true);
  60. </script>
  61. </html>

image.png
先捕获,后冒泡,与绑定顺序无关,默认是冒泡

image.png
image.png
结果不一样

事件冒泡

addEventListener(‘click’,function(){},false); false:冒泡
从事件源开始触发的事件会传递触发父元素的同一事件 此例中为click

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. <style>
  9. .wrapper{
  10. display: block;
  11. width: 300px;
  12. height: 300px;
  13. background-color: red;
  14. }
  15. .outer{
  16. display: block;
  17. width: 200px;
  18. height: 200px;
  19. background-color: green;
  20. }
  21. .inner{
  22. display: block;
  23. width: 100px;
  24. height: 100px;
  25. background-color: blue;
  26. }
  27. </style>
  28. </head>
  29. <body>
  30. <div class="wrapper">
  31. <div class="outer">
  32. <div class="inner"></div>
  33. </div>
  34. </div>
  35. </body>
  36. <script>
  37. var wrapper = document.getElementsByClassName('wrapper')[0],
  38. outer = wrapper.getElementsByClassName('outer')[0],
  39. inner = outer.getElementsByClassName('inner')[0];
  40. wrapper.addEventListener('click',function(){
  41. console.log('wrapper');
  42. },false);
  43. outer.addEventListener('click',function(){
  44. console.log('outer');
  45. },false);
  46. inner.addEventListener('click',function(){
  47. console.log('inner');
  48. },false);
  49. </script>
  50. </html>

image.png

事件捕获

addEventListener(‘click’,function(){},true); true:冒泡
从事件源的最顶层父元素开始触发并依次触发其子元素 直至事件源 此例中为click
事件源:触发事件的对象

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. <style>
  9. .wrapper{
  10. display: block;
  11. width: 300px;
  12. height: 300px;
  13. background-color: red;
  14. }
  15. .outer{
  16. display: block;
  17. width: 200px;
  18. height: 200px;
  19. background-color: green;
  20. }
  21. .inner{
  22. display: block;
  23. width: 100px;
  24. height: 100px;
  25. background-color: blueviolet;
  26. }
  27. </style>
  28. </head>
  29. <body>
  30. <div class="wrapper">
  31. wrapper
  32. <div class="outer">
  33. outer
  34. <div class="inner">inner</div>
  35. </div>
  36. </div>
  37. </body>
  38. <script>
  39. var wrapper = document.getElementsByClassName('wrapper')[0],
  40. outer = wrapper.getElementsByClassName('outer')[0],
  41. inner = outer.getElementsByClassName('inner')[0];
  42. wrapper.addEventListener('click',function(){
  43. console.log('wrapper');
  44. },true);
  45. outer.addEventListener('click',function(){
  46. console.log('outer');
  47. },true);
  48. inner.addEventListener('click',function(){
  49. console.log('inner');
  50. },true);
  51. </script>
  52. </html>

image.png

事件源不存在捕获或冒泡 按照代码顺序执行

image.png

没有冒泡与捕获的事件

focus blur change submit reset select

阻止冒泡与捕获

w3c: e.stopPropagation()
IE:e.cancelBubble = true

封装cancelBubble阻止冒泡与捕获方法

  1. //阻止冒泡与捕获
  2. function cancelBubble(e){
  3. var e = e || window.event;//因为ie8 e里面拿不到事件,事件在window.event里面
  4. if(e.stopPropagation){
  5. e.stopPropagation();
  6. }else{
  7. e.cancelBubble = true
  8. }
  9. }

调用方法
image.png

阻止默认事件

1.return false //仅支持句柄事件中使用

2.e.preventDefault() //IE9不兼容

3.e.returnValue = false; //IE9以下

封装preventDefaultEvent阻止默认行为函数

  1. //阻止默认函数行为
  2. function preventDefaultEvent(e){
  3. var e = e || window.event;
  4. if(e.preventDefault){
  5. e.preventDefault();
  6. }else{
  7. e.returnValue = false;
  8. }
  9. }

image.png

应用场景

1.允许a标签之外的元素进行页面跳转 点击icon

  1. <body>
  2. <a href="http://www.baidu.com" class="link" target="_blank">
  3. <div class="inner">点击</div>
  4. </a>
  5. </body>
  6. <script>
  7. var inner = document.getElementsByClassName('inner')[0];
  8. inner.onclick = function(e){
  9. var e = e || window.event;
  10. e.preventDefault();
  11. console.log('我点击了');
  12. }
  13. </script>

2.表单的跳转的刷新

  1. <body>
  2. <form action="">
  3. <input type="text" name="content"/>
  4. <input type="submit" id="submit" value="提交"/>
  5. </form>
  6. </body>
  7. <script>
  8. var submit = document.getElementById('submit');
  9. submit.onclick = function(e){
  10. var e = e || window.event;
  11. e.preventDefault();
  12. console.log('提交了');
  13. }
  14. </script>

阻止前
image.png
阻止后
image.png
HTML小知识 :点击提交会将url上带上其他input name的参数

  1. <form action="">
  2. <input type="text" name="content"/>
  3. <input type="submit" id="submit" value="提交"/>
  4. </form>