日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > HTML >内容正文

HTML

深入学习SAP UI5框架代码系列之三:HTML原生事件 VS UI5 Semantic事件

發布時間:2023/12/19 HTML 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 深入学习SAP UI5框架代码系列之三:HTML原生事件 VS UI5 Semantic事件 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

這是Jerry 2020年的第80篇文章,也是汪子熙公眾號總共第262篇原創文章。

系列目錄

(0) SAP UI5應用開發人員了解UI5框架代碼的意義

(1) UI5 module懶加載機制

(2) UI5 控件渲染機制

(3) HTML原生事件 VS SAP UI5 Semantic事件(本文)

(4) UI5控件元數據實現細節

(5) UI5控件的實例數據實現細節

(6) UI5控件數據綁定的實現原理

(7) UI5控件數據綁定的三種模式:One Way,Two Way和OneTime實現原理比較

(8) UI5控件ID的生成邏輯

(9) UI5控件的多語言(國際化,Internationalization,i18n)支持的實現原理

(10) XML視圖里的button控件

(11) button控件和它背后的DOM元素

本文將討論SAP UI5控件的事件處理,全文會圍繞下圖表現出的差異來闡述。

首先用一個簡單的例子來回顧HTML原生事件處理原理。

有這樣一個簡單的HTML頁面,里面使用了一個HTML原生button標簽,通過οnclick="copyText"注冊了一個名為copyText的事件處理函數。

點擊按鈕之后,響應函數copyText將Field1的值拷貝到Field2去。這個通過onclick注冊的事件處理函數,在Chrome開發者工具里可以直接查看。

除了onclick之外,調用瀏覽器原生的addEventListener方法也能給DOM元素注冊事件。

在企業級web應用里,DOM樹的結構通常都不簡單。例如僅僅包含一個簡單button控件的SAP UI5應用,頁面渲染出來后也會自動生成5個div標簽:

如果每個需要響應事件的控件,都使用onclick或者addEventListener給DOM元素注冊一個事件處理函數,隨著DOM事件處理函數數量的增加,web應用的性能會降低。因此SAP UI5引入了另一種所謂Semantic(語義)事件的概念,來完成UI5控件的事件注冊和響應工作。

使用Jerry文章 一個用于SAP UI5學習的腳手架應用,沒有任何后臺API的依賴 提到的腳手架,開發一個只包含sap.ui.commons.button的UI5應用:

上圖的Elements標簽頁里,顯示的是SAP UI5應用渲染完畢后,生成的HTML原生代碼。里包含的button標簽的生成邏輯,我們已經在前一篇文章 深入學習SAP UI5框架代碼系列之二:UI5 控件的渲染器 里介紹過了。

我們采用與前一個原生HTML button例子同樣的操作方式,在Chrome開發者工具里檢查UI5應用里該button的Event Listeners,卻什么也沒發現。

選中"Ancestors"前面的勾之后,一下子顯示了很多條目出來:

展開條目中的click,發現SAP UI5把click事件注冊在button標簽的父節點,即id為content的div標簽上了,如下圖所示。

再看看UI5應用里sap.ui.commons.Button的事件注冊代碼:

這里并沒有出現HTML原生事件click的身影,而將一個包含了屬性名稱press,值為JavaScript函數的JavaScript對象,作為輸入參數,傳入了UI5 Button的構造函數里:

用戶點擊這個按鈕時,觸發的應該是名稱為click的事件,和我們在這里為press事件注冊的處理函數有什么關系?

在UI5 button的實現源代碼里能找到答案。切換到Chrome開發者工具的Sources標簽頁,快捷鍵Ctrl + O,輸入button,選擇第一個結果Button-dbg.js:

這里能看到,press作為button支持的事件,定義在Button-dbg.js里:

下面這段代碼的含義是,當UI5 button有click事件發生時,如果其本身處于enabled并且是visible狀態,則fire一個Press事件(this.firePress()):

因此,正是Button實現里的這個onclick函數,實現了從事件click映射到事件press的任務。

上圖調試器里168行的this.firePress調用,最終如何成功地調用到UI5程序里針對press事件注冊的處理函數的呢?

還記得這個系列的前一篇文章 深入學習SAP UI5框架代碼系列之一:UI5 Module的懶加載機制 里介紹的一個知識點嗎?

SAP UI5運行時為所有的Module維護了一個注冊表,以鍵值對的數據結構存儲了這些Module的信息,鍵的數據類型為string,值類型即window.eval()將加載好的JavaScript文件內容作為輸入參數,執行后返回的JavaScript對象。

類似的原理,SAP UI5里每個控件都維護了一個鍵值對結構的事件注冊表mEventRegistry, 鍵的數據類型string,存儲事件名稱,值類型為數組,里面存放了針對該事件,應用程序實現的響應函數。

下圖展示的是我腳手架應用里的button控件的事件注冊表,只包含一條記錄,鍵為press,值為一個數組,里面唯一的元素即我在腳手架應用里實現的包含了alert調用的事件響應函數。

下圖展示的邏輯是:

(1) SAP UI5框架從第237行的控件事件注冊表里,根據事件名稱press,取出存放其事件處理函數的數組;

(2) 遍歷該數組,在for循環里用JavaScript function原型提供的call方法,對這些響應函數進行調用,完成事件響應:

至此又引出了一個新的問題:button控件的事件注冊表mEventRegistry里的那唯一的條目,是何時填充進去的?

再回憶本系列第一篇文章里介紹的SAP UI5控件的原型鏈:

Button->Control->Element->ManagedObject->EventProvider->BaseObject.

UI5應用里這一行語句:

new sap.ui.commons.Button()

會依次執行控件原型鏈上每一個節點對應的構造函數。控件事件注冊表mEventRegistry的填充操作,就發生在EventProvider這個節點的構造函數里:

上圖的變量oValue,就是我new一個button實例時傳入的press事件的處理函數。在第1192行代碼里,調用attachPress將oValue指向的函數進行注冊。函數attachPress最終調用EventProvider的attachEvent方法,將鍵值對寫入mEventRegistry:

至此有最后一個問題還未解答:本文開頭部分展示的Chrome開發者工具里,SAP UI5頁面渲染后生成的button標簽,在Event Listeners一欄里觀察不到任何響應函數。而在其父節點,id為content的div標簽里,在click事件下卻能觀察到響應函數。

Button父節點的div標簽上的click方法,和本文討論了這么長時間的button事件注冊表里的press事件,到底有何關系?

按鈕被點擊時,查看調試器里顯示的調用棧最外一層,發現SAP UI5的jquery-dbg.js, 響應的是HTML原生的click事件,且觸發該事件的對象的的確確是id為content的div標簽,而不是button標簽,這一點可以從event.currentTarget的值來確認。

以上圖調用棧中綠色的線為分隔,綠線下方的代碼,處理的是HTML原生的點擊事件click,同時完成了將click事件,經div投遞給其子節點,button標簽的任務。

綠線上方的Button.onclick, 前文我們已經闡述過,通過this.firePress將click事件映射成press事件,后續SAP UI5的所有事件處理,均圍繞這個press事件進行。

按照SAP UI5開發團隊大佬Andreas Kunz的介紹,button這種press事件稱為Semantic事件。同HTML原生的click事件直接通過onclick或addEventListener注冊在HTML DOM元素上不同,Semantic event的注冊和調用都是通過SAP UI5框架的JavaScript代碼施加在SAP UI5自行實現的控件上,比HTML原生的DOM事件處理和響應輕量得多,能避免隨著DOM樹復雜度的增加而造成的應用性能下降。

引入Semantic事件后,UI5控件不直接響應HTML原生事件,而是通過一個叫做UIArea的實體,來接收用戶觸發的HTML原生事件,并將其dispatch給UI5控件,后者再將其映射成一一對應的Semantic事件,并調用應用程序里實現的響應函數。這里的UIArea可以類比成設計模式里的Facade(外觀)模式,對SAP UI5的應用開發人員屏蔽了底層事件映射的復雜度。

上圖的UIArea的詳細描述,在SAP UI5官方文檔里有記載。

下圖高亮的一段對UIArea的闡述,展開來講就是Jerry本文的內容,大家感興趣的可以移步這個鏈接繼續閱讀。

如果把本文提到的Semantic事件換個叫法,比如稱其為虛擬事件,那么很容易聯想到Angular,Vue和React里引入的Virtual DOM(虛擬DOM)概念。從本質上說,這些前端框架都采取增加框架實現復雜度的代價,引入一個中間抽象層,來減少直接在JavaScript層操作DOM層造成的性能開銷。

順便說一句,AngularJS里的控件注冊實現,同SAP UI5思路一致:同樣未采取將事件處理函數直接注冊到HTML DOM元素上的機制。

下圖是一個Angularjs應用,第22行的ng-click指令,告訴Angularjs框架,超鏈接被點擊后,根據模型字段name,進行排序。

Angularjs框架如何解析這個ng-click指令,并完成事件注冊的?

在Angularjs應用bootstrap階段,框架會遍歷HTML DOM tree,遞歸調用compileNodes方法,逐一解析每一個包含了ng指令的元素:

當解析到包含了ng-click = "sortField = ‘name’"的a標簽時,調用Angular元素element的on方法,進行事件注冊:

查看on方法的實現代碼可知:Angularjs也并未將事件響應函數注冊到DOM元素上,而是同SAP UI5一樣,在框架內維護了一個控件事件注冊表,this.$$listeners(SAP UI5的名稱叫做mEventRegistry),采用鍵值對的數據結構,來存儲事件名稱和其對應的事件響應函數。

Angularjs應用里,事件響應函數被調用時的調用棧截圖:

關于SAP UI5和Angularjs的事件處理機制比較的更多細節,可以參考我的SAP社區博客:

Compare Event handling mechanism: SAPUI5 and Angular

本系列下一篇文章介紹的內容:UI5控件元數據實現細節。

感謝閱讀。

系列目錄

(0) SAP UI5應用開發人員了解UI5框架代碼的意義

(1) UI5 module懶加載機制

(2) UI5 控件渲染機制

(3) HTML原生事件 VS SAP UI5 Semantic事件(本文)

(4) UI5控件元數據實現細節

(5) UI5控件的實例數據實現細節

(6) UI5控件數據綁定的實現原理

(7) UI5控件數據綁定的三種模式:One Way,Two Way和OneTime實現原理比較

(8) UI5控件ID的生成邏輯

(9) UI5控件的多語言(國際化,Internationalization,i18n)支持的實現原理

(10) XML視圖里的button控件

(11) button控件和它背后的DOM元素

更多Jerry的原創文章,盡在:“汪子熙”:

總結

以上是生活随笔為你收集整理的深入学习SAP UI5框架代码系列之三:HTML原生事件 VS UI5 Semantic事件的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。