首頁  >  文章  >  web前端  >  如何自動取得HTML5的data-*屬性範例程式碼詳解

如何自動取得HTML5的data-*屬性範例程式碼詳解

黄舟
黄舟原創
2017-03-11 16:37:551426瀏覽

專案中需要設計一系列的自訂標籤,於是涉及標籤的屬性如何存取。使用 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('p');
	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(&#39;data-&#39;) != -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
    <p data-id="2"></p>
</listview>

<script>
var el = document.querySelector(&#39;#foo&#39;);
alert(el.querySelector(&#39;p&#39;).dataset.id);
</script>

問題小結:

  1. ##瀏覽器必須能夠支援querySelector/querySelectorAll 方法,否則該方法也沒有意義;

  2. 只能從取得元素的方法提供dataset。例如事件處理器中參數 e 的 e.tartget. dataset 則是空物件。

  3. 如上程式碼所示,單一的 querySelector() 是經過 querySelectorAll(),當中有遍歷數組的操作,能否適當優化一下,使用原生的來做?

  4. 對於 CSS Selector Engine 速度敏感的同學,本方法不適用。因為修改系統方法,可見必然效能會下降。但可以保證,這種下降是屬於小幅度的;

  5. 尚不支援 documeny.getElementByID,待增加之。

  6. #

以上是如何自動取得HTML5的data-*屬性範例程式碼詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn