JS 浅谈JavaScript之事件 超、凢脫俗 2023-10-18 14:59 72阅读 0赞 转载: [https://www.cnblogs.com/wangjiming/p/9983023.html][https_www.cnblogs.com_wangjiming_p_9983023.html] 一 简述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等; ![1066923-20181120154928961-345122100.png][] (二)JavaScript在浏览器中的地位 如上图,javascript处于浏览器中的核心位置,负责解释和执行js脚本,内置于浏览器中,通过浏览器提供的API来访问。 (三)JavaScript构成 关于javascript的构成,大致可归结为三个部分:ECMAScript,DOM和BOM。 1.ECMAScript是对js的约束和规范,如基本语法结构; 2.DOM就是文档对象模型,是交互的资源,如html文档; 3.BOM主要是对浏览器本身描述,如浏览器名称,版本号等; ![1066923-20181120153648621-1643664870.png][] (四)JavaScript基本执行原理 这里不深入谈及javascript的深层次执行原理,只是大致描述一下,关于更深层次的,在后续文章推出,与大家分享。 JS的执行原理,用一句话来归结之:单线程异步。下图很好地表述该过程。 所有的执行函数统一放在队列中进行排队。 ![1066923-20181120160928226-1658071354.png][] 二 事件流 所谓事件流,也可理解为事件的轨迹。一般地,将事件流分为三个阶段:捕获阶段,目标阶段和冒泡阶段。 ![1066923-20181120112502758-155581526.png][] 下图为三个阶段的大致流程图。 ![1066923-20181119144004341-2134250795.png][] (一)捕获阶段 捕获阶段处于事件流的第一阶段,该阶段的主要作用是捕获截取事件。在DOM中,该阶段始于Document,结束于body(当然,在现在的很 多高版本浏览器中,该过程结束于目标元素,只不过不执行目标元素而已,这也体现了目标元素具有双重范围)。 ![1066923-20181120104541584-1535157954.png][] (二)目标阶段 目标阶段处于事件流的第二阶段,该阶段的主要作用是执行绑定事件。一般地,该阶段具有双重范围,即捕获阶段的结束,冒泡阶段的开始; (三)冒泡阶段 冒泡阶段处于事件流的第三阶段,该阶段的主要作用是将目标元素绑定事件执行的结果返回给浏览器,处理不同浏览器之间的差异,主要在该阶段完成。 ![1066923-20181120105005392-1451237566.png][] (四)三阶段在Dom中的完整流程 ![1066923-20181120105100341-81774584.png][] 三 事件处理程序 js事件处理程序按照种类来划分,大致可分为五大类:HTML事件处理程序,DOM0级事件处理程序,DOM2级事件处理程序,IE事件处理程序和跨浏览器事件处理程序。 尤其是DOM0,DOM2和IE事件处理程序,利用它们之间的差异化有效地解决浏览器差异问题,从而实现跨浏览器的兼容性问题。 ![1066923-20181120111447285-909585539.png][] (一)html事件处理程序 所谓html事件处理程序,就是在dom结构中嵌套js代码。在html中,元素支持的所有事件,都可以使用与相应事件处理程序同名的html特性来指定,这个特性的值应该是能执行的js代码。 如点击事件。 <body> <!--html事件处理程序--> <input type="button" value="请点击" οnclick="alert('测试html事件处理程序!!')"/> </body> 当然,一般不采用如上方法,常规的做法是,将js代码定义在目标元素外部。因此,与如上相同功能的定义为: 目标元素 <body> <!--html事件处理程序--> <input type="button" value="请点击" οnclick="HtmlEventHandlerProc()"/> </body> 外部js <script> function HtmlEventHandlerProc() { alert('测试html事件处理程序!!'); } </script> Tip: 1.事件处理程序中的代码,能够访问全局作用域中的任何变量; 2.每个function()存在一个局部变量,即事件对象event,通过event变量,可以直接访问事件对象。 <body> <input type="button" value="请点击" οnclick="alert(event.type)"/> </body> 执行结果 ![1066923-20181119175708786-1326590569.png][] 3.在函数内部,this值等于事件的目标元素。 <body> <input type="button" value="请点击" οnclick="alert(this.value)"/> </body> 执行结果 ![1066923-20181119175632587-1201560688.png][] this具有扩展作用域的功能,其功能相当于 ![复制代码][copycode.gif] function myfunction() { with (document) { with (this) { //add your logic } } } ![复制代码][copycode.gif] 如果当前元素是一个表单元素,则作用域还会包含访问表单元素(父元素)的入口。 ![复制代码][copycode.gif] function myfunction() { with (document) { with (this.form) { with (this) { //add your logic } } } } ![复制代码][copycode.gif] 这样做,有什么本质意义呢?当然是想让事件处理程序更快捷访问表单其他字段(无需引用表单元素就能访问) <form> <input type="text" name="userName" value="Alan_beijing" /> <input type="button" value="测试表单元素" οnclick="alert(userName.value)" /> </form> 执行结果 ![1066923-20181119180630834-1810940330.png][] 4.html事件处理程序存在哪些缺点? 缺点一:时差问题 缺点二:扩展的作用域链在不同浏览器中会导致不同结果 缺点三:html代码与js代码高度耦合 (二)DOM0级事件处理程序 DOM0级事件很好地解决了html和js代码强耦合的问题。 1.为元素绑定事件 <table> <tbody> <tr> <td> <p>1</p> <p>2</p> <p>3</p> <p>4</p> </td> <td> <p><code>var</code> <code>btn = document.getElementById(</code><code>'myBtn'</code><code>);</code></p> <p><code>btn.onclick = </code><code>function</code> <code>() { </code></p> <p><code> </code><code>alert(</code><code>'Clicked'</code><code>);</code></p> <p><code>}</code></p> </td> </tr> </tbody> </table> 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); 执行结果: ![1066923-20181119183413106-767864858.png][] 2.添加多个事件处理程序 ![复制代码][copycode.gif] var btn = document.getElementById("myBtn"); btn.addEventListener("click", function () { alert(this.id); }, false); btn.addEventListener("click", function myfunction() { alert("添加的第二个事件处理程序"); }, false); ![复制代码][copycode.gif] 执行结果: ![1066923-20181119183327326-413060916.png][] ![1066923-20181119183303008-1919816520.png][] 3 移除事件处理程序 通过addEventListener()添加的事件处理陈旭只能使用removeEventListener()来移除,移除时,传入的参数与添加的程序时使用的参数相同 (这意味着匿名函数不能通过removeEventListener()来删除) 匿名函数不能删除 ![复制代码][copycode.gif] var btn = document.getElementById("myBtn"); btn.addEventListener("click", function () { alert(this.id); }, false); //不能删除,因为是匿名函数 btn.removeEventListener("click", function () { alert(this.id); }, false); ![复制代码][copycode.gif] 非匿名函数能删除 ![复制代码][copycode.gif] var btn = document.getElementById("myBtn"); var handler = function () { alert(this.id); }; btn.addEventListener("click", handler, false); //删除事件处理程序 btn.removeEventListener("click", handler, false); ![复制代码][copycode.gif] (四)IE事件处理程序 IE提供了两个方法来绑定和卸载事件处理程序,attachEvent()和detachEvent(),这两个方法均接收两个参数,即事件处理程序名称和事件处理程 序函数,并且在冒泡阶段添加(IE8及更早版本只支持冒泡) 1.为目标按钮添加绑定事件 var btn = document.getElementById("myBtn"); btn.attachEvent("onclick", function () { alert("IE事件处理程序!!"); }); 2.为目标按钮添加绑定事件 多个执行绑定事件的结果是倒过来的。 ![复制代码][copycode.gif] var btn = document.getElementById("myBtn"); btn.attachEvent("onclick", function () { alert("IE事件处理程序1!!"); }); btn.attachEvent("onclick", function () { alert("IE事件处理程序2!!"); }); ![复制代码][copycode.gif] 3.为目标元素移除事件处理程序 注意:匿名事件处理程序是不能够移除的 ![复制代码][copycode.gif] var btn = document.getElementById("myBtn"); var handler = function () { alert("IE事件处理程序"); }; //绑定事件 btn.attach("onclick", handler); //移除事件 btn.detachEvent("onclick", handler); ![复制代码][copycode.gif] (五)跨浏览器事件处理程序 在跨浏览器中,无非就是三种选择:DOM0级选择(不常用,基本被废弃),DOM2级选择和IE选择(不常用,IE8及以下版本)。 ![复制代码][copycode.gif] //定义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); ![复制代码][copycode.gif] 四 事件类型 内容相对比较简单,这里就暂且列举主要内容,若有需要,会在下篇文章论述。 ![1066923-20181119152446712-1276410849.png][] 五 事件对象及其事件委托 介于文章篇幅有限,暂且列举主要内容,代码部分将在下篇文章论述。 ![1066923-20181120164509114-1512210773.png][] [https_www.cnblogs.com_wangjiming_p_9983023.html]: https://www.cnblogs.com/wangjiming/p/9983023.html [1066923-20181120154928961-345122100.png]: https://img2018.cnblogs.com/blog/1066923/201811/1066923-20181120154928961-345122100.png [1066923-20181120153648621-1643664870.png]: https://img2018.cnblogs.com/blog/1066923/201811/1066923-20181120153648621-1643664870.png [1066923-20181120160928226-1658071354.png]: https://img2018.cnblogs.com/blog/1066923/201811/1066923-20181120160928226-1658071354.png [1066923-20181120112502758-155581526.png]: https://img2018.cnblogs.com/blog/1066923/201811/1066923-20181120112502758-155581526.png [1066923-20181119144004341-2134250795.png]: https://img2018.cnblogs.com/blog/1066923/201811/1066923-20181119144004341-2134250795.png [1066923-20181120104541584-1535157954.png]: https://img2018.cnblogs.com/blog/1066923/201811/1066923-20181120104541584-1535157954.png [1066923-20181120105005392-1451237566.png]: https://img2018.cnblogs.com/blog/1066923/201811/1066923-20181120105005392-1451237566.png [1066923-20181120105100341-81774584.png]: https://img2018.cnblogs.com/blog/1066923/201811/1066923-20181120105100341-81774584.png [1066923-20181120111447285-909585539.png]: https://img2018.cnblogs.com/blog/1066923/201811/1066923-20181120111447285-909585539.png [1066923-20181119175708786-1326590569.png]: https://img2018.cnblogs.com/blog/1066923/201811/1066923-20181119175708786-1326590569.png [1066923-20181119175632587-1201560688.png]: https://img2018.cnblogs.com/blog/1066923/201811/1066923-20181119175632587-1201560688.png [copycode.gif]: https://common.cnblogs.com/images/copycode.gif [1066923-20181119180630834-1810940330.png]: https://img2018.cnblogs.com/blog/1066923/201811/1066923-20181119180630834-1810940330.png [1066923-20181119183413106-767864858.png]: https://img2018.cnblogs.com/blog/1066923/201811/1066923-20181119183413106-767864858.png [1066923-20181119183327326-413060916.png]: https://img2018.cnblogs.com/blog/1066923/201811/1066923-20181119183327326-413060916.png [1066923-20181119183303008-1919816520.png]: https://img2018.cnblogs.com/blog/1066923/201811/1066923-20181119183303008-1919816520.png [1066923-20181119152446712-1276410849.png]: https://img2018.cnblogs.com/blog/1066923/201811/1066923-20181119152446712-1276410849.png [1066923-20181120164509114-1512210773.png]: https://img2018.cnblogs.com/blog/1066923/201811/1066923-20181120164509114-1512210773.png
还没有评论,来说两句吧...