Home  >  Article  >  Web Front-end  >  Detailed explanation of how to automatically obtain the data-* attributes of HTML5 sample code

Detailed explanation of how to automatically obtain the data-* attributes of HTML5 sample code

黄舟
黄舟Original
2017-03-11 16:37:551389browse

The project needs to design a series of custom labels, so it involves how to access the properties of the labels. If you use the data-* attribute of HTML5, you can directly access the dataset.attribute name after obtaining the element. The type of dataset is DOMStringMap {}, a MAP object, which is still a key / value object, which is more convenient to use. However, we encountered a compatibility problem, and it is not supported on some old browsers such as Android 2.3.

For this, we can write a compatibility patch. The main principle is to "hijack" methods such as document.querySelector/querySelectorAll to obtain elements, and then provide a custom field dataset = {....} to achieve similar standard writing. Of course, simply, you can provide an API method like getDataAttrib() to get the attribute, and the effect will be the same. The reason why we do not adopt this method but another method is to better move closer to the standard and use a consistent access method for everyone.

My implementation is as follows:

// 如浏览器不支持 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;
    }
})();

Considering that querySelector’s method of obtaining elements is sufficient, the documeny.getElementByID(“#id”) method is currently not provided.

Please note: querySelector /querySelectorAll executed on non-document objects will not be supported and the dataset will not be returned. This problem was solved by rewriting the Element.prototype method on 2013.1.16. The detailed process is as follows:

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

Test example:

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

Problem summary:

  1. The browser must be able to support the querySelector/querySelectorAll method, otherwise This method also makes no sense;

  2. The dataset can only be provided from the method that gets the elements. For example, e.tartget.dataset of parameter e in the event handler is an empty object.

  3. As shown in the above code, a single querySelector() is passed through querySelectorAll(), which includes the operation of traversing the array. Can it be appropriately optimized and used natively?

  4. For students who are sensitive to CSS Selector Engine speed, this method is not applicable. Because the system method is modified, it can be seen that the performance will inevitably decrease. But it can be guaranteed that this decrease is small;

  5. documeny.getElementByID is not yet supported and will be added.

The above is the detailed content of Detailed explanation of how to automatically obtain the data-* attributes of HTML5 sample code. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn