欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

浅谈JavaScript之Event(上篇)

程序员文章站 2022-10-16 12:23:06
一 简述JavaScript及其在浏览器中的地位 (一) 浏览器主要构成 虽然不同浏览器之间存在差异(如Google Chrome,Firefox,Safari和IE等),但单从浏览器构成来说,大同小异,大致可归结为如下几类: 1.User Interface(用户界面):所谓用户界面,就是通过浏览 ......

一  简述javascript及其在浏览器中的地位

(一)  浏览器主要构成

虽然不同浏览器之间存在差异(如google chrome,firefox,safari和ie等),但单从浏览器构成来说,大同小异,大致可归结为如下几类:

1.user interface(用户界面):所谓用户界面,就是通过浏览器渲染出来,让用户可见的界面,如地址栏,书签菜单栏等;

2.browser engine(浏览器引擎):主要操作呈现的引擎界面;

3.rendering engine(渲染引擎):负责渲染响应请求内容,如负责解析html和css;

4.networking(网络):负责网络呼叫处理,如http请求;

5.js interpreter(javascript 解释器):负责解析和执行javascript代码;

6.ui back(ui后端):用于绘制组合框和窗口等基本组建;

7.data persistence(数据持久):通常用来持久化存储少量数据,如cookie等;

浅谈JavaScript之Event(上篇)

 

(二)javascript在浏览器中的地位

 如上图,javascript处于浏览器中的核心位置,负责解释和执行js脚本,内置于浏览器中,通过浏览器提供的api来访问。

(三)javascript构成

关于javascript的构成,大致可归结为三个部分:ecmascript,dom和bom。

1.ecmascript是对js的约束和规范,如基本语法结构;

2.dom就是文档对象模型,是交互的资源,如html文档;

3.bom主要是对浏览器本身描述,如浏览器名称,版本号等;

浅谈JavaScript之Event(上篇)

 

(四)javascript基本执行原理

 这里不深入谈及javascript的深层次执行原理,只是大致描述一下,关于更深层次的,在后续文章推出,与大家分享。

 js的执行原理,用一句话来归结之:单线程异步。下图很好地表述该过程。

所有的执行函数统一放在队列中进行排队。

 浅谈JavaScript之Event(上篇)

二  事件流

所谓事件流,也可理解为事件的轨迹。一般地,将事件流分为三个阶段:捕获阶段,目标阶段和冒泡阶段。

浅谈JavaScript之Event(上篇)

下图为三个阶段的大致流程图。

浅谈JavaScript之Event(上篇)

 (一)捕获阶段

捕获阶段处于事件流的第一阶段,该阶段的主要作用是捕获截取事件。在dom中,该阶段始于document,结束于body(当然,在现在的很

多高版本浏览器中,该过程结束于目标元素,只不过不执行目标元素而已,这也体现了目标元素具有双重范围)。

浅谈JavaScript之Event(上篇)

 

 (二)目标阶段

目标阶段处于事件流的第二阶段,该阶段的主要作用是执行绑定事件。一般地,该阶段具有双重范围,即捕获阶段的结束,冒泡阶段的开始;

(三)冒泡阶段

冒泡阶段处于事件流的第三阶段,该阶段的主要作用是将目标元素绑定事件执行的结果返回给浏览器,处理不同浏览器之间的差异,主要在该阶段完成。

浅谈JavaScript之Event(上篇)

(四)三阶段在dom中的完整流程

浅谈JavaScript之Event(上篇)

 

三   事件处理程序

js事件处理程序按照种类来划分,大致可分为五大类:html事件处理程序,dom0级事件处理程序,dom2级事件处理程序,ie事件处理程序和跨浏览器事件处理程序。

尤其是dom0,dom2和ie事件处理程序,利用它们之间的差异化有效地解决浏览器差异问题,从而实现跨浏览器的兼容性问题。

浅谈JavaScript之Event(上篇)

 

(一)html事件处理程序

所谓html事件处理程序,就是在dom结构中嵌套js代码。在html中,元素支持的所有事件,都可以使用与相应事件处理程序同名的html特性来指定,这个特性的值应该是能执行的js代码。

如点击事件。

<body>
    <!--html事件处理程序-->
    <input type="button" value="请点击" onclick="alert('测试html事件处理程序!!')"/>
</body>

当然,一般不采用如上方法,常规的做法是,将js代码定义在目标元素外部。因此,与如上相同功能的定义为:

目标元素

<body>
    <!--html事件处理程序-->
    <input type="button" value="请点击" onclick="htmleventhandlerproc()"/>
</body>

外部js

<script>
    function htmleventhandlerproc() {
        alert('测试html事件处理程序!!');
    }
</script>

tip:

1.事件处理程序中的代码,能够访问全局作用域中的任何变量;

2.每个function()存在一个局部变量,即事件对象event,通过event变量,可以直接访问事件对象。

<body>
   <input type="button" value="请点击" onclick="alert(event.type)"/>
</body>

执行结果

浅谈JavaScript之Event(上篇)

3.在函数内部,this值等于事件的目标元素。

<body>
    <input type="button" value="请点击" onclick="alert(this.value)"/>
</body>

执行结果

浅谈JavaScript之Event(上篇)

 this具有扩展作用域的功能,其功能相当于

function myfunction() {
        with (document) {
            with (this) {
                //add your logic
           }
      }
 }

如果当前元素是一个表单元素,则作用域还会包含访问表单元素(父元素)的入口。

  function myfunction() {
        with (document) {
            with (this.form) {
                with (this) {
                    //add your logic
                }
            }
        }
    }

这样做,有什么本质意义呢?当然是想让事件处理程序更快捷访问表单其他字段(无需引用表单元素就能访问)

 <form>
         <input type="text" name="username" value="alan_beijing" />
         <input type="button" value="测试表单元素" onclick="alert(username.value)" />
     </form>

执行结果

浅谈JavaScript之Event(上篇)

 4.html事件处理程序存在哪些缺点?

   缺点一:时差问题

   缺点二:扩展的作用域链在不同浏览器中会导致不同结果

   缺点三:html代码与js代码高度耦合

(二)dom0级事件处理程序

dom0级事件很好地解决了html和js代码强耦合的问题。

1.为元素绑定事件

var btn = document.getelementbyid('mybtn');
btn.onclick = function () {
    alert('clicked');
}

2.为元素解除事件

btn.onclick = null;

(三)dom2级事件处理程序

dom2级事件定义了两个方法来为目标元素绑定事件处理程序(addeventlistener())和解除事件处理程序(removeeventlistener()),所有节点中都包含这两个方法,并且他们都接收三个参数:

要处理的事件名,事件处理程序和一个布尔值(true表示是在捕获阶段进行,false表示在冒泡阶段进行)

1.为事件添加click事件处理程序(冒泡阶段进行)

var btn = document.getelementbyid("mybtn");
btn.addeventlistener("click", function () {
     alert(this.id);
}, false);

执行结果:

浅谈JavaScript之Event(上篇)

2.添加多个事件处理程序

var btn = document.getelementbyid("mybtn");
btn.addeventlistener("click", function () {
   alert(this.id);
}, false);

btn.addeventlistener("click", function myfunction() { alert("添加的第二个事件处理程序"); }, false);

执行结果:

浅谈JavaScript之Event(上篇)

浅谈JavaScript之Event(上篇)

 3 移除事件处理程序

通过addeventlistener()添加的事件处理陈旭只能使用removeeventlistener()来移除,移除时,传入的参数与添加的程序时使用的参数相同

(这意味着匿名函数不能通过removeeventlistener()来删除)

匿名函数不能删除

var btn = document.getelementbyid("mybtn");
    btn.addeventlistener("click", function () {
        alert(this.id);
    }, false);

    //不能删除,因为是匿名函数
    btn.removeeventlistener("click", function () {
        alert(this.id);
    }, false);

非匿名函数能删除

    var btn = document.getelementbyid("mybtn");
    var handler = function () {
        alert(this.id);
    };

    btn.addeventlistener("click", handler, false);
    //删除事件处理程序
    btn.removeeventlistener("click", handler, false);

(四)ie事件处理程序

ie提供了两个方法来绑定和卸载事件处理程序,attachevent()和detachevent(),这两个方法均接收两个参数,即事件处理程序名称和事件处理程

序函数,并且在冒泡阶段添加(ie8及更早版本只支持冒泡)

1.为目标按钮添加绑定事件

var btn = document.getelementbyid("mybtn");
btn.attachevent("onclick", function () {
   alert("ie事件处理程序!!");
});

2.为目标按钮添加绑定事件

多个执行绑定事件的结果是倒过来的。

 var btn = document.getelementbyid("mybtn");
 btn.attachevent("onclick", function () {
       alert("ie事件处理程序1!!");
 });

 btn.attachevent("onclick", function () {
      alert("ie事件处理程序2!!");
 });

3.为目标元素移除事件处理程序

注意:匿名事件处理程序是不能够移除的

    var btn = document.getelementbyid("mybtn");
    var handler = function () {
        alert("ie事件处理程序");
    };
    //绑定事件
    btn.attach("onclick", handler);
    //移除事件
    btn.detachevent("onclick", handler);

(五)跨浏览器事件处理程序

在跨浏览器中,无非就是三种选择:dom0级选择(不常用,基本被废弃),dom2级选择和ie选择(不常用,ie8及以下版本)。

//定义eventutil
    var eventutil = {
        addhandler: function (element, type, handler) {
            if (element.addeventlistener) {
                element.addeventlistener(type, handler, false);
            } else if (element.attachevent) {
                element.attachevent("on" + type, handler);
            }
        },
        removehandler: function (element, type, handler) {
            if (element.removeeventlistener) {
                element.removeeventlistener(type, handler, false);
            } else if (element.detachevent) {
                element.detachevent("on" + type, handler);
            } else {
                element["on" + type] = null;
            }
        }
    }

    //调用
    var btn = document.getelementbyid("mybtn");
    var handler = function () {
        alert("事件处理程序跨浏览器!!");
    };
    //绑定事件处理程序
    eventutil.addhandler(btn, "click", handler);
    //移除事件处理程序
    eventutil.removehandler(btn, "click", handler);

四  事件类型

内容相对比较简单,这里就暂且列举主要内容,若有需要,会在下篇文章论述。

浅谈JavaScript之Event(上篇)

五  事件对象及其事件委托

介于文章篇幅有限,暂且列举主要内容,代码部分将在下篇文章论述。

浅谈JavaScript之Event(上篇)

六  版权区

  • 感谢您的阅读,若有不足之处,欢迎指教,共同学习、共同进步。
  • 博主网址:http://www.cnblogs.com/wangjiming/。
  • 极少部分文章利用读书、参考、引用、抄袭、复制和粘贴等多种方式整合而成的,大部分为原创。
  • 如您喜欢,麻烦推荐一下;如您有新想法,欢迎提出,邮箱:2098469527@qq.com。
  • 可以转载该博客,但必须著名博客来源。