自动获取 HTML5 的 data-* 属性

简介: 项目中需要设计一系列的自定义标签,于是涉及到标签的属性如何访问。使用 HTML5 的 data-* 属性的话,获取元素后直接访问 dataset.属性名称 即可,dataset 的类型为 DOMStringMap {},一个 MAP 对象,仍是 key / value 式的对象,使用上比较方便。

项目中需要设计一系列的自定义标签,于是涉及到标签的属性如何访问。使用 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>
问题小结:
  1. 浏览器必须能够支持 querySelector/querySelectorAll 方法,否则该方法也没有意义;
  2. 只能从获取元素的方法提供 dataset。比如事件处理器中参数 e 的 e.tartget. dataset 则是空对象。
  3. 如上代码所示,单个的 querySelector() 是经过 querySelectorAll(),当中有遍历数组的操作,能否适当优化一下,使用原生的来做?
  4. 对于 CSS Selector Engine 速度敏感的同学,本方法不适用。因为修改系统方法,可见必然性能会下降。但可以保证,这种下降是属于小幅度的;
  5. 尚不支持 documeny.getElementByID,待增加之。
目录
相关文章
|
10月前
|
移动开发 HTML5
HTML5 表单属性3
`&lt;input&gt;` 标签的 `formaction`、`formenctype` 和 `formmethod` 属性分别用于指定表单提交的 URL 地址、数据编码类型和提交方法,这些属性可覆盖 `&lt;form&gt;` 标签中的相应属性,并且主要适用于 `type=&quot;submit&quot;` 和 `type=&quot;image&quot;` 的输入类型。
|
9月前
|
移动开发 JavaScript 前端开发
HTML5 表单属性7
`pattern` 属性使用正则表达式验证 `&lt;input&gt;` 元素的值,适用于 `text`, `search`, `url`, `tel`, `email`, 和 `password` 类型。
|
9月前
|
移动开发 UED HTML5
HTML5 表单属性6
`min`、`max` 和 `step` 属性用于限制 `&lt;input&gt;` 标签中的数值或日期范围。例如,可以设置日期选择器的最早和最晚日期,或限制数字输入框的值范围。`multiple` 属性允许在 `&lt;input&gt;` 中选择多个值,适用于邮箱和文件类型。这些属性增强了表单控件的功能性和用户体验。
|
10月前
|
移动开发 HTML5
HTML5 表单属性4
`formnovalidate` 属性是一个布尔属性,用于 `&lt;input&gt;` 元素,指示该输入在表单提交时不需验证,可覆盖 `&lt;form&gt;` 元素的 `novalidate` 属性,常与 `type=&quot;submit&quot;` 一起使用。示例中展示了如何通过两个提交按钮(一个使用验证,另一个不使用)实现不同的表单提交方式。
|
9月前
|
移动开发 HTML5
HTML5 表单属性5
`height` 和 `width` 属性用于 `&lt;input&gt;` 标签中的 `image` 类型,定义图像的高度和宽度。
|
10月前
|
移动开发 JavaScript 前端开发
HTML5 表单属性2
`novalidate` 是 HTML `&lt;form&gt;` 元素的布尔属性,用于禁用浏览器的默认表单验证功能。当此属性存在时,浏览器不会检查表单字段是否符合预设的验证规则,允许开发者通过 JavaScript 等手段自定义验证逻辑。
|
9月前
|
移动开发 数据安全/隐私保护 HTML5
HTML5 表单属性8
`required`属性确保表单提交前输入框不能为空,适用于多种类型的 `&lt;input&gt;` 标签,如文本、邮箱、密码等。`step`属性则用于指定输入域中合法数值的间隔,常与`max`和`min`属性配合使用,适用于数字、日期等类型。例如,设置`&lt;input type=&quot;number&quot; step=&quot;3&quot;&gt;`可使输入值以3为单位递增或递减。
|
10月前
|
移动开发 UED HTML5
HTML5 表单属性1
HTML5为&lt;form&gt;和&lt;input&gt;标签引入了多个新属性,增强了表单的功能性和用户体验。其中,&lt;form&gt;新增了autocomplete和novalidate属性;&lt;input&gt;则增加了如autofocus、formaction、placeholder等13个新属性,支持更精细的表单控制和数据验证。例如,autocomplete属性允许表单或输入字段提供自动完成功能,提高用户填写效率。
|
10月前
|
搜索推荐 前端开发 UED
哪些 HTML 全局属性在 SEO 优化中比较重要?
【10月更文挑战第27天】这些HTML全局属性通过不同的方式为搜索引擎提供了更丰富、准确的页面信息,有助于提高页面的可索引性、相关性和用户体验,从而在SEO优化中发挥着重要的作用。开发者应充分重视并合理运用这些属性,以提升网站在搜索引擎中的排名和流量。
126 12
|
10月前
|
前端开发 搜索推荐 算法