淺談JavaScript事件(上篇)

来源:https://www.cnblogs.com/wangjiming/archive/2018/11/20/9983023.html
-Advertisement-
Play Games

一 簡述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在瀏覽器中的地位

 如上圖,javascript處於瀏覽器中的核心位置,負責解釋和執行js腳本,內置於瀏覽器中,通過瀏覽器提供的API來訪問。

(三)JavaScript構成

關於javascript的構成,大致可歸結為三個部分:ECMAScript,DOM和BOM。

1.ECMAScript是對js的約束和規範,如基本語法結構;

2.DOM就是文檔對象模型,是交互的資源,如html文檔;

3.BOM主要是對瀏覽器本身描述,如瀏覽器名稱,版本號等;

 

(四)JavaScript基本執行原理

 這裡不深入談及javascript的深層次執行原理,只是大致描述一下,關於更深層次的,在後續文章推出,與大家分享。

 JS的執行原理,用一句話來歸結之:單線程非同步。下圖很好地表述該過程。

所有的執行函數統一放在隊列中進行排隊。

 

二  事件流

所謂事件流,也可理解為事件的軌跡。一般地,將事件流分為三個階段:捕獲階段,目標階段和冒泡階段。

下圖為三個階段的大致流程圖。

 (一)捕獲階段

捕獲階段處於事件流的第一階段,該階段的主要作用是捕獲截取事件。在DOM中,該階段始於Document,結束於body(當然,在現在的很

多高版本瀏覽器中,該過程結束於目標元素,只不過不執行目標元素而已,這也體現了目標元素具有雙重範圍)。

 

 (二)目標階段

目標階段處於事件流的第二階段,該階段的主要作用是執行綁定事件。一般地,該階段具有雙重範圍,即捕獲階段的結束,冒泡階段的開始;

(三)冒泡階段

冒泡階段處於事件流的第三階段,該階段的主要作用是將目標元素綁定事件執行的結果返回給瀏覽器,處理不同瀏覽器之間的差異,主要在該階段完成。

(四)三階段在Dom中的完整流程

 

三   事件處理程式

js事件處理程式按照種類來劃分,大致可分為五大類:HTML事件處理程式,DOM0級事件處理程式,DOM2級事件處理程式,IE事件處理程式和跨瀏覽器事件處理程式。

尤其是DOM0,DOM2和IE事件處理程式,利用它們之間的差異化有效地解決瀏覽器差異問題,從而實現跨瀏覽器的相容性問題。

 

(一)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>

執行結果

3.在函數內部,this值等於事件的目標元素。

<body>
    <input type="button" value="請點擊" onclick="alert(this.value)"/>
</body>

執行結果

 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>

執行結果

 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);

執行結果:

2.添加多個事件處理程式

var btn = document.getElementById("myBtn");
btn.addEventListener("click", function () {
   alert(this.id);
}, false);

btn.addEventListener(
"click", function myfunction() { alert("添加的第二個事件處理程式"); }, false);

執行結果:

 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);

四  事件類型

內容相對比較簡單,這裡就暫且列舉主要內容,若有需要,會在下篇文章論述。

五  事件對象及其事件委托

介於文章篇幅有限,暫且列舉主要內容,代碼部分將在下篇文章論述。

六  版權區

  • 感謝您的閱讀,若有不足之處,歡迎指教,共同學習、共同進步。
  • 博主網址:http://www.cnblogs.com/wangjiming/。
  • 極少部分文章利用讀書、參考、引用、抄襲、複製和粘貼等多種方式整合而成的,大部分為原創。
  • 如您喜歡,麻煩推薦一下;如您有新想法,歡迎提出,郵箱:[email protected]
  • 可以轉載該博客,但必須著名博客來源。

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前端發展很快,現代瀏覽器原生 API 已經足夠好用。我們並不需要為了操作 DOM、Event 等再學習一下 jQuery 的 API。同時由於 React、Angular、Vue 等框架的流行,直接操作 DOM 不再是好的模式,jQuery 使用場景大大減少。本項目總結了大部分 jQuery API ...
  • 什麼是前後端分離? 前後端為什麼要分離? 前後端怎麼樣分離的? 前後端分離給我們前端技術人員的開髮帶來什麼樣的好處? 下麵我就帶著這些問題,來簡單談談我瞭解到的前後端分離情況。 在講前後端分離之前,讓我們先講一講什麼是MVC? MVC誕生於上世紀70年代,是一種經典的設計模式,全名為 Model-V ...
  • 索引 1、對象深拷貝 2、網路圖片轉base64, 線上圖片點擊下載 3、對象深拷貝 4、對象深拷貝 5、對象深拷貝 6、對象深拷貝 1、對象深拷貝 2、網路圖片轉base64, 線上圖片點擊下載 3、對象深拷貝 4、對象深拷貝 5、對象深拷貝 6、對象深拷貝 1、對象的深拷貝(一級屬性拷貝和多級屬 ...
  • 之前做項目的時候,一直都想著做一個上下滾動的公告欄,作為展示網站的最新公告信息,因為剛開始自己的思路並不是太清晰,在網上找了很多的源碼,但是卻發現都不能讓自己滿意,有的還會出現一些小問題,比如,有時候公告上下滾動的時候,兩條公告會重疊在一起。最後我還是決定自己寫一個上下滾動的公告欄。 jQuery實 ...
  • json與object的區別:1、JSON是對象,但對象不一定是JSON2、對象的組成是由屬性和屬性值,也就是KEY->VALUE對組成,value可是是任意的數據類型,當value為一個函數的時候,這個時候叫做方法。而你通過 JSON.parse()傳入的字元串並裡面有VALUE為function ...
  • 歡迎大家前往 "騰訊雲+社區" ,獲取更多騰訊海量技術實踐乾貨哦~ 本文由 "前端林子" 發表於 "雲+社區專欄" 隨著前端技術的發展,請求伺服器數據的方法早已不局限於ajax、jQuery的ajax方法。各種js庫已如雨後春筍一般,蓬勃發展,本文主要想介紹其中的axios和fetch。 0.引入 ...
  • 1)直接使用變數 備註:如需使用字元$或{,請使用`\`或`$\{` 2)多行書寫 ...
  • 現要獲取box中,除了第一個之外的其他的div : 其中n後面的數字,是幾就是從第幾個開始獲取。 例子中從第二個div開始獲取, 所以是 n+2 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...