基本用法
querySelector
該方法返回滿足條件的單個元素。按照深度優先和先序遍歷的原則使用參數提供的CSS選擇器在DOM進行查找,返回第一個滿足條件的元素。 ----> querySelector得到一個DOM
var element = document.querySelector('#container');//返回id為container的dom var element = document.querySelector('div#container');//返回id為container的首個div var element = document.querySelector('.foo,.bar');//返回帶有foo或者bar樣式類的首個元素
querySelectorAll
該方法返回所有滿足條件的元素,結果是個nodeList集合。查找規則與前面所述一樣。 ----> querySelectorAll 得到一個偽數組 DOM
var elements = document.querySelectorAll('div.foo');//返回所有帶foo類樣式的d<div id="box"> //surface blog
querySelectorAll支持屬性操作 這個用也比較多
<div id="box" > <ul> <li data-href='http://www.qq.com'>tagname 111</li> <li class="surfaces">這是clase 222</li> <li class="surfaces">這是class 333</li> <li class="surfaces" data-href='http://www.baidu.com'>這是class 444</li> </ul> </div>
document.getElementById("box").addEventListener("click",function(){ var attr=document.querySelectorAll('[data-href]'); console.log(attr); },!1);
移動端 getElementById(id), querySelector 和querySelectorAll 已經能夠滿足大部分dom操作需求了;
高級用法
先附上相關 html http://www.cnblogs.com/surfaces/
<div id="box"> <ul> <li >tagname 111</li> <li class="surfaces">這是clase 222</li> <li class="surfaces">這是class 333</li> <li class="surfaces">這是class 444</li> </ul> </div>
先看看 querySelector的高級應用
var query = document.querySelector.bind(document); //單個的
var query_id=query('#box'); //dom id var query_class=query('.surfaces'); // dom class var query_tagname=query('li') //dom 標簽
獲取看到這里,你會懷疑 這都可以,我們跑一下代碼看看 結果
console.log('query'+query_id.innerHTML); // console.log('query'+query_class.innerHTML); //// 第一個 222 console.log('query'+query_tagname.innerHTML); //// 第一個 222 query_id.addEventListener('click',function(){ console.log('click_query_id'+this.innerHTML); //'click surfaces 2222 }); query_class.addEventListener('click',function(){ var e=e||window.event; console.log('click_query_class'+this.innerHTML); //'click surfaces 2222 e.stopPropagation(); }); query_tagname.addEventListener('click',function(e){ var e=e||window.event; console.log('click_query_tagname'+this.innerHTML); //'click surfaces 2222 e.stopPropagation(); });
上張圖 看看控制台的結果
然后我們再看看 queryAelectorAll的高級用法
var $=queryAll = document.querySelectorAll.bind(document); //集合 個人感覺最犀利 surfaces
var $id=$('#box'); //id var $class=$('.lione'); //class var $tagname=$('li'); //tagName
跑一下這段代碼看看
var $id=$('#box'); //id var $class=$('.surfaces'); //class var $tagname=$('li'); //tagName console.log('queryAll'+$id[0].innerHTML); console.log('queryAll'+$class[0].innerHTML); //222 console.log('queryAll'+$tagname[0].innerHTML);//111 $id[0].addEventListener('click',function(){ console.log('click_queryAll'+this.innerHTML); //'click surfaces 2222 }); $class[0].addEventListener('click',function(e){ console.log('click_$class'+this.innerHTML); //'click surfaces 2222 e.stopPropagation(); }); $tagname[0].addEventListener('click',function(e){ console.log('click_$tagname'+this.innerHTML); //'click surfaces 2222 e.stopPropagation(); });
看看控制台的結果
根據上面的用法 我們可以 看看這種 C 寫法
var fromId = document.getElementById.bind(document); var fromClass = document.getElementsByClassName.bind(document); var fromTag = document.getElementsByTagName.bind(document);
var fromId_box=fromId('box'); var fromClass_surfaces=fromClass('surfaces'); var fromTag_li=fromTag('li'); console.log('fromId'+fromId_box.innerHTML); console.log('fromClass'+fromClass_surfaces[0].innerHTML); //222 console.log('fromTag'+fromTag_li[0].innerHTML);//111
上面 C 寫法沒啥大問題,C 寫法 不推薦;還不如以下的 老老實實的,性能又好;
var doc=document; var box=doc.getElementById("box"); var li=box.getElementsByTagName("li"); var surfaces=box.getElementsByClassName("surfaces");
另外;我們梳理下基於 querySelectorAll的事件綁定,從 Array.prototype中剽竊了 forEach 方法來完成遍歷
Array.prototype.forEach.call(document.querySelectorAll('.surfaces'), function(el){ el.addEventListener('click', someFunction); }); //通過 bind() 遍歷DOM節點的函數。。 var unboundForEach = Array.prototype.forEach, forEach = Function.prototype.call.bind(unboundForEach); forEach(document.querySelectorAll('.surfaces'), function (el) { el.addEventListener('click', someFunction); });
http://www.cnblogs.com/surfaces/
關於bind()的用法, bind()與call(),apply()用法 類似,都是改變當前的this指針。這里簡單闡述做個示例;
document.getElementById("box").addEventListener("click",function(){ var self=this; //緩存 this 對象 setTimeout(function(){ self.style.borderColor='red'; },500) },false); document.getElementById("box").addEventListener("click",function(){ setTimeout(function(){ this.style.borderColor='red'; }.bind(this), 500); //通過bind 傳入 this },false);
另外一種事件綁定方法,不在闡述;
//以下是Andrew Lunny已經想出來的一些東西: https://remysharp.com/2013/04/19/i-know-jquery-now-what#backToTheFutureToday-heading
var $ = document.querySelectorAll.bind(document); Element.prototype.on = Element.prototype.addEventListener; $('#somelink')[0].on('touchstart', handleTouch);
我們根據這個結合bind 一起使用
//我們將綁定事件在 完善一下 Element.prototype.on = Element.prototype.addEventListener; queryAll('#box')[0].on('click',function(){ //on 類似 jquery //document.getElementById("box").on("click",function(){ setTimeout(function(){ this.style.borderColor='blue'; console.log('on事件 邊框變藍色'); }.bind(this), 500); //通過bind 傳入 this });
關於bind兼容性 擴展;
Function.prototype.bind = Function.prototype.bind || function (target) { var self = this; return function (args) { if (!(args instanceof Array)) { args = [args]; } self.apply(target, args); } };
bind擴展閱讀:一起Polyfill系列:Function.prototype.bind的四個階段
總結一下:移動端dom操作 ,其實只要 getElementById(id), querySelector 和querySelectorAll 已經能夠滿足大部分的需求了;
document.querySelectorAll.bind(document);
document.querySelector.bind(document);
缺點:
並不適合那些相對復雜或者表單多的單頁;也不適合簡單項目的主頁;如果多人協作,不利於維護;
上面的始終綁定的document,有時候不一定從document查找;沒有content上下文;如document.querySelector("#box").querySelector('.surfaces'); 限定范圍在id為box下的class surfaces;
看看 Remy Sharp 封裝的min.js ;值得學習思考 這種思想;或許你覺得不好,一般般,或者不適合項目啊 之類的;這邊不是重點;重點是 你就是想不到可以這樣寫,重點是 看別人怎樣寫的,為什么可以這樣寫,優點是什么;
/*globals Node:true, NodeList:true*/ $ = (function (document, window, $) { // Node covers all elements, but also the document objects var node = Node.prototype, nodeList = NodeList.prototype, forEach = 'forEach', trigger = 'trigger', each = [][forEach], // note: createElement requires a string in Firefox dummy = document.createElement('i'); nodeList[forEach] = each; // we have to explicitly add a window.on as it's not included // in the Node object. window.on = node.on = function (event, fn) { this.addEventListener(event, fn, false); // allow for chaining return this; }; nodeList.on = function (event, fn) { this[forEach](function (el) { el.on(event, fn); }); return this; }; // we save a few bytes (but none really in compression) // by using [trigger] - really it's for consistency in the // source code. window[trigger] = node[trigger] = function (type, data) { // construct an HTML event. This could have // been a real custom event var event = document.createEvent('HTMLEvents'); event.initEvent(type, true, true); event.data = data || {}; event.eventName = type; event.target = this; this.dispatchEvent(event); return this; }; nodeList[trigger] = function (event) { this[forEach](function (el) { el[trigger](event); }); return this; }; $ = function (s) { // querySelectorAll requires a string with a length // otherwise it throws an exception var r = document.querySelectorAll(s || '☺'), length = r.length; // if we have a single element, just return that. // if there's no matched elements, return a nodeList to chain from // else return the NodeList collection from qSA return length == 1 ? r[0] : r; }; // $.on and $.trigger allow for pub/sub type global // custom events. $.on = node.on.bind(dummy); $[trigger] = node[trigger].bind(dummy); return $; })(document, this);