对此,我们可以写一个兼容性的补丁。主要原理是在“劫持” 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('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 <p data-id="2"></p> </listview> <script> var el = document.queryselector('#foo'); alert(el.queryselector('p').dataset.id); </script>
问题小结:
浏览器必须能够支持 queryselector/queryselectorall 方法,否则该方法也没有意义;
只能从获取元素的方法提供 dataset。比如事件处理器中参数 e 的 e.tartget. dataset 则是空对象。
如上代码所示,单个的 queryselector() 是经过 queryselectorall(),当中有遍历数组的操作,能否适当优化一下,使用原生的来做?
对于 css selector engine 速度敏感的同学,本方法不适用。因为修改系统方法,可见必然性能会下降。但可以保证,这种下降是属于小幅度的;
尚不支持 documeny.getelementbyid,待增加之。
以上就是如何自动获取html5的data-*属性示例代码详解的详细内容。
