自動獲取HTML5的data-*屬性
專案中需要設計一系列的自定義標籤,於是涉及到標籤的屬性如何訪問。使用 HTML5 的 data-* 屬性的話,獲取元素後直接訪問 dataset.屬性名稱 即可,dataset 的型別為 DOMStringMap {},一個 MAP 物件,仍是 key / value 式的物件,使用上比較方便。但卻遇到一個相容性的問題, 在 Android 2.3 等的一些舊有瀏覽器上尚不支援。
對此,我們可以寫一個相容性的補丁。主要原理是在“劫持” document.querySelector/querySelectorAll 這類獲取元素的方法之後,通過提供自定義的欄位 dataset = {….} 即可實現類似標準寫法。當然,簡單地,你可以通過一個 API 方法來提供類似 getDataAttrib() 獲取屬性,效果一樣。我們之所以不採取這種方式,而採用另外一種方式,是為了更好向標準靠攏,使用大家都一致的訪問方式。
我的實現如下:
// 如瀏覽器不支援 HTML5 data-* 屬性,設定一個。 ;(function(){ // 測試元素 var el; el = document.createElement(`div`); el.setAttribute(`data-id`, `111`); if(!el.dataset){ Element.prototype.dataset = {}; var querySelectorAll = document.querySelectorAll; // 儲存一個 document.querySelectorAll = function(){ var resultEls = querySelectorAll.apply(this, arguments); for(var resultEl, i = 0, j = resultEls.length; i < j; i++){ resultEl = resultEls[i]; resultEl.dataset = getAttrib(resultEl.attributes) } return resultEls; } // 也就是單個的 document.querySelectorAll()。不儲存,直接覆蓋 document.querySelector = function(){ var resultEls = document.querySelectorAll.apply(this, arguments); return resultEls ? resultEls[0] : null; }; } el = null; // 要完全移除 dummy 元素,是否這樣就 ok? /** * 把元素儲存為 JSON 物件 * @param {Element.attributes} 元素屬性集合 * @return {Object} */ function getAttrib(attributes) { if (!attributes) return; var hash = {}; for (var attribute, i = 0, j = attributes.length; i < j; i++) { attribute = attributes[i]; if(attribute.nodeName.indexOf(`data-`) != -1){ hash[attribute.nodeName.slice(5)] = attribute.nodeValue; } } return hash; } })();
考慮到 querySelector 獲取元素的方式已經足夠,故所以當前沒有提供 documeny.getElementByID(“#id”) 方法。
請注意:對於非 document 物件身上執行的 querySelector /querySelectorAll 將不支援,仍不會返回 dataset。 針對該問題,已於2013.1.16 通過重寫 Element.prototype 方法解決。詳細過程如下:
if(!canSupportDataSet()){ Element.prototype.dataset = {}; modifyQuerySelectorAll_By(document); // document 的好像不一樣…… modifyQuerySelectorAll_By(Element.prototype); } /** * 覆蓋系統的 querySelector/querySelectorAll 方法。 * @param host {Element.prototype/Document} */ function modifyQuerySelectorAll_By(host){ var querySelectorAll = host.querySelectorAll; // 儲存一個 host.querySelectorAll = function(){ var resultEls = querySelectorAll.apply(this, arguments); for(var resultEl, i = 0, j = resultEls.length; i < j; i++){ resultEl = resultEls[i]; resultEl.dataset = getAttrib(resultEl.attributes) } return resultEls; } // 也就是單個的 document.querySelectorAll()。不儲存,直接覆蓋 host.querySelector = function(){ var resultEls = host.querySelectorAll.apply(this, arguments); return resultEls ? resultEls[0] : null; }; }
測試例子:
<listview id="foo" data-id="1"> Hello World <div data-id="2"></div> </listview> <script> var el = document.querySelector(`#foo`); alert(el.querySelector(`div`).dataset.id); </script>
問題小結:
- 瀏覽器必須能夠支援 querySelector/querySelectorAll 方法,否則該方法也沒有意義;
- 只能從獲取元素的方法提供 dataset。比如事件處理器中引數 e 的 e.tartget. dataset 則是空物件。
- 如上程式碼所示,單個的 querySelector() 是經過 querySelectorAll(),當中有遍歷陣列的操作,能否適當優化一下,使用原生的來做?
- 對於 CSS Selector Engine 速度敏感的同學,本方法不適用。因為修改系統方法,可見必然效能會下降。但可以保證,這種下降是屬於小幅度的;
- 尚不支援 documeny.getElementByID,待增加之。
相關文章
- data-* 自定義屬性
- Android自動化-如何獲取檢視元素屬性?Android
- 獲取影像的屬性
- HTML5 data-*HTML
- opencv 獲取影像的屬性OpenCV
- 根據屬性字串獲取屬性值字串
- Python的tkinter獲取元件屬性和設定元件屬性Python元件
- JavaScript 獲取 checked 屬性值JavaScript
- render函式處理動態獲取img的src屬性函式
- jQuery - 獲取內容和屬性jQuery
- PHP獲取檔案基本屬性的方法PHP
- C#反射設定屬性值和獲取屬性值C#反射
- 揭秘Java反射:如何輕鬆獲取類的屬性及父類屬性Java反射
- C# 獲取修改了哪些屬性C#
- Power Automate 獲取使用者屬性
- lambda方法引用獲取欄位屬性
- 獲取json串裡的某個屬性值JSON
- C#獲取某個物件的屬性值C#物件
- HTML5 novalidate 屬性HTML
- jQuery捕獲-獲取DOM元素內容和屬性jQuery
- 設定和獲取元素固有屬性值
- 透過Lambda函式的方式獲取屬性名稱函式
- 獲取類屬性值,當前類,父類
- selenium用XPATH直接獲取屬性值 需要使用.get_attribute(“屬性名”)
- HTML5 Audio & Video 屬性解析HTMLIDE
- postman自動呼叫獲取tokenPostman
- Poco 框架實操:獲取節點屬性的高效技巧 (一)框架
- Poco框架實操:獲取節點屬性的高效技巧(一)框架
- Laravel 模型關聯的『動態屬性』,Eloquent: 關聯以後可以獲取模型的集合Laravel模型
- python獲取、修改mysql資料庫欄位屬性PythonMySql資料庫
- 010-jQuery獲取和設定內容屬性jQuery
- laravel Eloquent模型 關於模型關聯屬性獲取Laravel模型
- JS - 獲取CSS屬性值 getComputedStyle()與currentStyle()、style()方法JSCSS
- 你瞭解HTML5的download屬性嗎?HTML
- html5/css3新增屬性HTMLCSSS3
- JS獲取照片拍攝的角度屬性,用於旋轉控制JS
- js獲取iframe和父級之間元素,方法、屬,獲取iframe的高度自適應iframe高度JS
- 獲取List集合物件中某一列屬性值物件
- C# 隨機給一個全部資訊都未知的類型別,如何獲取該類的類名、屬性個數、屬性名、屬性的資料型別、屬性值?C#隨機資料型別