自動獲取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,待增加之。
相關文章
- HTML5的data-*自定義屬性HTML
- jQuery data()方法和HTML5 data-*自定義屬性jQueryHTML
- data-* 自定義屬性
- html5標籤的data-*屬性用法簡單介紹HTML
- jQuery的data()函式操作html5的自定義data-*屬性jQuery函式HTML
- Android自動化-如何獲取檢視元素屬性?Android
- 獲取影像的屬性
- opencv 獲取影像的屬性OpenCV
- js如何獲取給定屬性的屬性值JS
- python 獲取類的屬性Python
- HTML5 data-*HTML
- JavaScript 獲取 checked 屬性值JavaScript
- javascript如何獲取屬性值JavaScript
- javascript獲取物件直接量中的屬性和屬性值JavaScript物件
- js獲取元素的方法與屬性JS
- 視窗屬性的獲取函式函式
- 自動生成屬性
- Python的tkinter獲取元件屬性和設定元件屬性Python元件
- render函式處理動態獲取img的src屬性函式
- 在url中通過屬性名獲取屬性值
- jQuery - 獲取內容和屬性jQuery
- PHP獲取檔案基本屬性的方法PHP
- jquery設定和獲取元素的屬性jQuery
- ms sql 獲取表欄位的屬性SQL
- C#反射設定屬性值和獲取屬性值C#反射
- 獲取dom的最終的css屬性值CSS
- 獲取物件屬性型別、屬性名稱、屬性值的研究:反射和JEXL解析引擎物件型別反射
- 揭秘Java反射:如何輕鬆獲取類的屬性及父類屬性Java反射
- lambda方法引用獲取欄位屬性
- 在Progress中獲取檔案屬性
- C# 獲取修改了哪些屬性C#
- selenium+python3 web自動化獲取html頁面元素屬性值方法PythonWebHTML
- C#獲取某個物件的屬性值C#物件
- js通過元素的class屬性獲取元素JS
- jQuery獲取id屬性值具有點的元素jQuery
- 使用jQuery獲取iframe元素的value屬性值jQuery
- iOS 執行時獲取類的所有屬性iOS
- jQuery捕獲-獲取DOM元素內容和屬性jQuery