事件及一些兼容性写法

DOM0 事件和DOM2级在事件监听使用方式上有什么区别?

  • DOM0事件监听方式就是把一个方法赋给一个元素的事件处理程序
    var Btn = document.querySelector('#btn');
    Btn.onclick = function(){
    alert(this);
    }
    var Btn = document.querySelector('#btn');
    Btn.onclick = function(){
    console.log(this);
    } //覆盖上一个函数
    使用DOM0级方法指定的事件处理程序被认为是元素的方法,此时事件处理程序是在元素的作用域里中运行,所以此时this指向的是元素本身。而且这种添加方式的缺陷是,只能存在一个处理程序,如果再次向同一个元素添加另外一个处理程序,上一个处理程序会被覆盖。

  • DOM2级事件监听方式两个方法用于处理指定和删除事件处理程序的操作,包含三个参数
    事件类型
    事件处理方法
    布尔参数,如果是true表示在捕获阶段调用事件处理程序,如果是false,则是在事件冒泡阶段处理
    var Btn = document.querySelector('#btn');
    Btn.addEventListener('click', function(){
    console.log(this);
    },true);
    通过addEventListener添加的事件处理程序只能通过removeEventListener移除,移除时参数与添加的时候相同,这就意味着刚才我们添加的匿名函数无法移除

attachEvent与addEventListener的区别?

参数个数不相同,这个最直观,addEventListener有三个参数,attachEvent只有两个,attachEvent添加的事件处理程序只能发生在冒泡阶段,addEventListener第三个参数可以决定添加的事件处理程序是在捕获阶段还是冒泡阶段处理(我们一般为了浏览器兼容性都设置为冒泡阶段)

第一个参数意义不同,addEventListener第一个参数是事件类型(比如click,load),而attachEvent第一个参数指明的是事件处理函数名称(onclick,onload)

事件处理程序的作用域不相同,addEventListener的作用域是元素本身,this是指的触发元素,而attachEvent事件处理程序会在全局变量内运行,this是window,所以刚才例子才会返回undefined,而不是元素id

为一个事件添加多个事件处理程序时,执行顺序不同,addEventListener添加会按照添加顺序执行,而attachEvent添加多个事件处理程序时顺序无规律(添加的方法少的时候大多是按添加顺序的反顺序执行的,但是添加的多了就无规律了),所以添加多个的时候,不依赖执行顺序的还好,若是依赖于函数执行顺序,最好自己处理,不要指望浏览器

解释IE事件冒泡和DOM2事件传播机制?

IE事件冒泡:即事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播。
当用户点击了<div>元素,click事件将按照<div>—><body>—><html>—>document的顺序进行传播。若在<div>和<body>上都定义了click事件,如下:

       <script type="text/javascript">
                var div=document.getElementById("myDiv");
                div.onclick=function(event){
                      alert("div");
               };
               document.body.onclick=function(event){
                  alert("body");
           };    
       </script>

     点击<div>,将先输出“div”,再输出“body”。

DOM2事件传播机制:
DOM2级事件”规定的事件流包含三个阶段:事件捕获阶段,处于目标阶段和事件冒泡阶段。首先发生的是事件捕获,然后是实际的目标接收到事件,最后阶段是冒泡阶段。以上面的HTML页面为例,若在<div>和<body>上都定义了click事件,如下:

  <script type="text/javascript">
           var div=document.getElementById("myDiv");    
           div.onclick=function(event){
           alert("div");
      };
           document.body.addEventListener("click",function(event){
           alert("event bubble");
      },false);
          document.body.addEventListener("click",function(event){
           alert("event catch");
       },true);
    
    </script>

 点击<div>,将先输出“event catch”,再输出“div”,最后输出“event bubble”。

如何阻止事件冒泡? 如何阻止默认事件?

兼容DOM的浏览器会将一个event对象传入事件处理程序中,这个event对象包含一个stopPropagation()方法,可以组织事件的进一步捕获或冒泡(取决于添加时的参数)。并且包含一个preventDefault()方法,可以取消事件的默认行为。(在事件处理程序里使用return false也可以)

对于IE来说,它的event对象具有cancelBubble属性,默认值为false,设置为true用来取消事件冒泡; 还有returnValue,默认值为true,设置为false用来取消事件的默认行为。

代码1:有如下代码,要求当点击每一个元素li时控制台展示该元素的文本内容。不考虑兼容

   <ul class="ct">
       <li>这里是</li>
       <li>饥人谷</li>
       <li>前端6班</li>
   </ul>
 <script>
     let List = document.getElementsByClassName('ct')[0];
       List.addEventListener('click',function(e){
       if(e.target.tagName.toLowerCase() === 'li'){
    console.log(e.target.innerText);
    }
     });
   </script>

补全代码,要求:

当点击按钮开头添加时在 元素前添加一个新元素,内容为用户输入的非空字符串;当点击结尾添加时在最后一个 li 元素后添加用户输入的非空字符串.
当点击每一个元素li时控制台展示该元素的文本内容。

      <ul class="ct">
       <li>这里是</li>
       <li>饥人谷</li>
       <li>任务班</li>
      </ul>
   <input class="ipt-add-content" placeholder="添加内容"/>
   <button id="btn-add-start">开头添加</button>
   <button id="btn-add-end">结尾添加</button>
      <script>
var addBtn = document.querySelector('#btn-add-start');
var ipt = document.querySelector('.ipt-add-content');
var end = document.querySelector('#btn-add-end');
var list = document.querySelector('.ct');
addBtn.addEventListener('click',function(){
    if(/\S/.test(ipt.value)) {
        var Li = document.createElement('li');
        Li.innerText = ipt.value;
        list.insertBefore(Li, list.firstChild)
    }else{
        return alert(false)
    }
});
end.addEventListener('click',function(){
    if(/\S/.test(ipt.value)) {
        var Li = document.createElement('li');
        Li.innerText = ipt.value;
        list.insertBefore(Li, list.lastChild)
    }else{
        return alert(false);
    }
});
list.addEventListener('click',function(e){
    if(e.target.tagName.toLowerCase() === 'li')
    console.log(e.target.innerText);
})
</script>

题目7: 补全代码,要求:当鼠标放置在li元素上,会在img-preview里展示当前li元素的data-img对应的图片。

   <ul class="ct">
      <li data-img="1.png">鼠标放置查看图片1</li>
      <li data-img="2.png">鼠标放置查看图片2</li>
      <li data-img="3.png">鼠标放置查看图片3</li>
   </ul>
 <div class="img-preview"></div>
<script>
var ct = document.querySelector('.ct');
var preview = document.querySelector('.img-preview');
var li = document.querySelector('.ct li');
ct.addEventListener('mouseover',function(e) {
    if (e.target.tagName.toLowerCase() === 'li') {
        var img = document.createElement('img')
        img.src = e.target.getAttribute('data-img');
        preview.appendChild(img)
    }
})
ct.addEventListener('mouseout',function(e) {
    if (e.target.tagName.toLowerCase() === 'li') {
    preview.innerHTML = '';
}
});
</script>

addevent compatible for IE

function addEvent(node, type, handler) {
if (!node) return false;
if (node.addEventListener) {
    node.addEventListener(type, handler, false);
    return true;
}
else if (node.attachEvent) {
    node['e' + type + handler] = handler;
    node[type + handler] = function() {
        node['e' + type + handler](window.event);
    };
    node.attachEvent('on' + type, node[type + handler]);
    return true;
}
return false;
}
在取消事件处理程序的时候
function removeEvent(node, type, handler) {
if (!node) return false;
if (node.removeEventListener) {
    node.removeEventListener(type, handler, false);
    return true;
}
else if (node.detachEvent) {
    node.detachEvent('on' + type, node[type + handler]);
    node[type + handler] = null;
}
return false;
}


//event arguments for IE
  function getEvent(e) {
  return e || window.event;
}

function getTarget(e) {
return e.target || e.scrElement;
}

function preventDefault(e) {
if (e.preventDefault)
    e.preventDefault();
 else
    e.returnValue = false;
}

function stopPropagation(e) {
if (e.stopPropagation)
    e.stopPropagation();
else
    e.cancelBubble = true;
 }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 声明:本文来源于http://www.webzsky.com/?p=731我只是在这里作为自己的学习笔记整理一下(...
    angryyan阅读 7,080评论 1 6
  • 一、问答 1. dom对象的innerText和innerHTML有什么区别? innerHTML: 也就是从对象...
    饥人谷_罗伟恩阅读 614评论 0 2
  • JavaScript 程序采用了异步事件驱动编程模型。在这种程序设计风格下,当文档、浏览器、元素或与之相关的对象发...
    劼哥stone阅读 1,273评论 3 11
  • 1.事件代理 事件代理:为子元素添加监听器转变为为父容器添加监听器,然后通过event.target判断具体操作的...
    IT男的成长记录阅读 537评论 0 0
  • 题目1: DOM0 事件和DOM2级在事件监听使用方式上有什么区别? Dom0级Dom0级事件处理程序是将一个函数...
    QQQQQCY阅读 320评论 0 0