如何解析 querySelectorAll 选择器引擎的结果并允许方法链接?

abb*_*tto 3 html javascript css css-selectors

简化示例代码:

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); }
    }
}
Run Code Online (Sandbox Code Playgroud)

我想这样使用它......:

$("div").innerHTML='It works!';
Run Code Online (Sandbox Code Playgroud)

...不是这样的...:

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

...或这个:

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

这是我得到的最接近的结果。我希望链接能够工作并与本机方法兼容:

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!');
Run Code Online (Sandbox Code Playgroud)

我决定构建这个引擎是为了更好地学习 JavaScript;它正在工作,但我希望我能从 Stack Overflow 的好心成员那里学到更多东西。任何帮助将非常感激!

T.J*_*der 5

我想这样使用它......:

$("div").innerHTML='It works!';
Run Code Online (Sandbox Code Playgroud)

...不是这样的...:

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

听起来您想将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");
Run Code Online (Sandbox Code Playgroud)

在那里,我们定义一个函数,并将其分配给您作为属性返回的数组。然后您可以在数组上调用该函数。(您可能希望使用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";
Run Code Online (Sandbox Code Playgroud)

在那里,我们用来Object.defineProperty为属性定义一个设置器。

在下面的评论中你说

我有一些原型可以在单独附加到 $ 函数时工作。示例:$('div').makeClass('this');当它们链接在一起时,它们不起作用。例子:$('div').makeClass('this').takeClass('that');

为了使链接工作,您需要return this;从每个函数中进行操作(因此 的结尾就makeClass可以了return this;)。这是因为当您链接时,例如obj.foo().bar(),您正在调用bar的返回值foo。因此,为了使链接起作用,您需要确保foo返回this(被调用的对象foo)。