2012-12-09 46 views
2

簡單的例子代碼:如何解析querySelectorAll選擇器引擎的結果並允許方法鏈接?

var $ = function(selector, node) { // Selector engine 
    var selector = selector.trim(), node = node || document.body; 
    if (selector != null) { 
     return Array.prototype.slice.call(node.querySelectorAll(selector), 0); } 
    } 
} 

我想用它像這樣...:

$("div").innerHTML='It works!'; 

...不是這樣...:

$("div")[0].innerHTML='It works only on the specified index!'; 

.. .or:

for(i=0;i<$('div');i++) { 
     $("div")[i].innerHTML='It works great but it's ugly!'; 
} 

這跟我接近。我想鏈接工作,併爲它與本地方法兼容:

if(!Array.prototype.innerHTML) { 
    Array.prototype.innerHTML = function(html) { 
     for (var i = 0; i < this.length; i++) { 
      this[i].innerHTML = html; 
     } 
    } 
} 

$("div").innerHTML('It works, but it ruins method chaining!'); 

我決定建立這個引擎,以更好地學習JavaScript;它正在工作,但我希望我能從Stack Overflow的類成員中學到更多東西。任何幫助將非常感激!

+0

我會回顧一些相關的庫和框架'.html()'和'.text()'它們是如何實現它的源代碼,如jQuery,MooTools,Prototype,YUI。 –

回答

4

我想用它像這樣...:

$("div").innerHTML='It works!'; 

...不是這樣...:

$("div")[0].innerHTML='It works only on the specified index!'; 

這聽起來像你想擁有分配給innerHTML對你的結果集分配innerHTML全部的結果。

要做到這一點,您必須直接或間接使用函數。

直接:

var $ = function(selector, node) { // Selector engine 
    var selector = selector.trim(), 
     node = node || document.body, 
     rv; 
    if (selector != null) { 
     rv = Array.prototype.slice.call(node.querySelectorAll(selector), 0); } 
     rv.setInnerHTML = setInnerHTML; 
    } 
    return rv; 
} 
function setInnerHTML(html) { 
    var index; 

    for (index = 0; index < this.length; ++index) { 
     this[index].innerHTML = html; 
    } 
} 

// Usage 
$("div").setInnerHTML("The new HTML"); 

在那裏,我們定義一個函數,我們把它分配給您傳回的屬性數組。然後你可以在數組上調用該函數。 (您可能需要使用Object.defineProperty如果可用來設置setInnerHTML屬性,因此你可以把它不可枚舉。)

間接(需要啓用ES5的JavaScript引擎):

var $ = function(selector, node) { // Selector engine 
    var selector = selector.trim(), 
     node = node || document.body, 
     rv; 
    if (selector != null) { 
     rv = Array.prototype.slice.call(node.querySelectorAll(selector), 0); } 
     Object.defineProperty(rv, "innerHTML", { 
      set: setInnerHTML 
     }); 
    } 
    return rv; 
} 
function setInnerHTML(html) { 
    var index; 

    for (index = 0; index < this.length; ++index) { 
     this[index].innerHTML = html; 
    } 
} 

// Usage 
$("div").innerHTML = "The new HTML"; 

在那裏,我們使用Object.defineProperty來定義屬性的setter。

在下面你的評論說

我有當單獨連接到$函數工作幾年的原型。例如:$('div').makeClass('this');當它們鏈接在一起時,它們不起作用。例如:$('div').makeClass('this').takeClass('that');

要鏈接的工作,你做的每個功能(這樣的makeClass年底會做return this;return this;。這是因爲當您鏈接時,例如obj.foo().bar(),您要撥打bar,返回值爲foo。因此,要使鏈接工作,請確保foo返回this(調用foo的對象)。

+0

感謝您的快速回復。出於演示目的,我只使用了innerHTML。我真的很好奇,看看我是否也可以用其他方法使用引擎。 – abbotto

+1

@ o0110o:除了獲取匹配列表之外,您沒有使用選擇器引擎。如果你想對結果對象有進一步的方法,你有兩種選擇:在創建它時將它們分配給每個實例,或者(這可能是更好的選擇)使結果對象不是真正的數組,但是你創建的東西帶有您想要添加的附加功能的原型。 –

+0

感謝您的建議T.J. – abbotto

0

這是什麼工作;這是一個稍微不同的語法,然後我在前面的例子中給出了,但最終的結果是一樣的。我得到了其他Stack Exchange成員的很大幫助,再次感謝大家。

var $ = function(selector, node) { // Selector engine 
    var selector = selector.trim(), node = node || document.body; 
    if (selector != null) { 
     return Array.prototype.slice.call(node.querySelectorAll(selector), 0); } 
    } 
} 

if(!Array.prototype.html) { 
    Array.prototype.html = function(html) { 
     for (var i = 0; i < this.length; i++) { 
      this[i].innerHTML = html; 
     } 
     return this; //<---- Silly me, my original code was missing this. 
    } 
} 

當我運行它,一切(包括鏈接)可以作爲期望:

$("div").html('hello world'); 

OUTPUT:

<div>hello world</div> 

乾杯!