【问题标题】:jQuery to Conventional Javascript mappingjQuery 到常规 Javascript 的映射
【发布时间】:2011-10-22 10:30:11
【问题描述】:

我只想将一些 jQuery 方法映射到它们的普通 Javascript DOM 方法;

例如

prev()
next()
before()
after()

如果你能提供 jQuery/Javascript 到类似 DOM 操作方法的映射,那就太好了。

【问题讨论】:

  • 为什么不直接看一下jQuery源码?
  • (它的来源是github.com/jquery/jquery/blob/master/src/traversing.js,但它是个脑筋急转弯,它的声明仍然是坚定的“jQuery”,而不是原生DOM方法)。
  • 完整功能中的方法?例如。 prevnext 采用选择器...

标签: javascript jquery html dom dom-manipulation


【解决方案1】:

这些 jQuery 方法在普通的基于 DOM 的 JS 中都没有精确的一对一模拟。如果他们这样做了,jQuery 就不需要实现自己的方法来完成这些任务。

您可以使用elem.previousSiblingelem.nextSibling 获取元素的上一个和下一个兄弟姐妹。例如,使用这种 HTML 结构:

<ul>
    <li>First</li>
    <li id="second">Second</li>
</ul>

你会使用这个 JS:

var elem = document.getElementById("second");
var p = elem.previousSibling;
alert(p.nodeType);

在这种情况下,第二个 LI 的前一个兄弟不是第一个 LI。相反,前一个兄弟是两个 LI 标记之间的空白区域。这样做是为了让您可以操作文档中除了实际的 HTML 元素之外的任何文本节点。 nextSibling 属性的工作原理相同。

这在理论上很好,但在实际使用中或多或少会让人头疼,因为您实际上很少或永远不需要操作文档中的空白。要解决此问题,请遍历检查nodeType 的兄弟姐妹。如果 nodeType 为 1,那么它是一个文本节点,所以跳到下一个,直到找到 nodeType 不是 1 的那个。

您可能会发现博客文章 Finding HTML elements using Javascript nextSibling and previousSibling 很有帮助。只要避免他使用的扩展 Object.prototype 的技术——这样做很容易打破 for/in 在对象上的循环。

对于before()after(),DOM 等价物是insertBefore()insertBefore() 在您想要的目标之后运行在兄弟姐妹上。但是,您不能只是将一些 HTML 放入其中并期望它能够工作。相反,您必须手动将每个元素、属性和值创建为 DOM 节点,然后插入它们。例如:

var welcomingDiv;

function sayHi(){
  welcomingDiv = document.createElement("div");
  welcomingDiv.innerHTML = "Welcome, and be amazed!";

  
  target = document.getElementById("a-tag-someplace");
  document.body.insertBefore(welcomingDiv, target);
}

这会将它插入到您的文档中,任何标签的 ID 为“a-tag-someplace”。不过,即使这是一种欺骗,因为 innerHTML 不是官方 JS 标准的一部分。如果您操作正确,则必须创建一个文本节点并将其附加到新创建的 DIV 中。

所以,简而言之:jQuery 让生活变得更加简单。不要在没有充分理由的情况下重新发明轮子。

【讨论】:

    【解决方案2】:
    prev() - previousSibling, its a property
    next() - nextSibling, its a property
    before() - insertBefore,
    after() - There is no insertAfter method but we implement it using insertBefore
    

    【讨论】:

    • 我相信它们实际上是 $(node.previousSibling) 等。人。是吗?
    • +1 请注意,“after”可以通过使用“insertBefore”来实现,正如你所提到的,或者在父元素上使用“appendChild”来实现在最后一个兄弟之后添加内容的情况。
    【解决方案3】:

    以下是TreeWalker(play with it at jsbin.com)的JavaScript实现。

    <html>
    <head></head>
    <body>
        <script>
            var NodeFilter = {
                FILTER_ACCEPT: 1,
                FILTER_REJECT: 2,
                FILTER_SKIP: 3,
                SHOW_ALL: -1,
                SHOW_ELEMENT: 1,
                SHOW_ATTRIBUTE: 2,
                SHOW_TEXT: 4,
                SHOW_CDATA_SECTION: 8,
                SHOW_ENTITY_REFERENCE: 16,
                SHOW_ENTITY: 32,
                SHOW_PROCESSING_INSTRUCTIONS: 64,
                SHOW_COMMENT: 128,
                SHOW_DOCUMENT: 256,
                SHOW_DOCUMENT_TYPE: 512,
                SHOW_DOCUMENT_FRAGMENT: 1024,
                SHOW_NOTATION: 2048
            };
    
            var TreeWalker = function (root, whatToShow, filter, expandEntityReferences) {
                this.root = root;
                this.whatToShow = whatToShow;
                this.filter = filter;
                this.expandEntityReferences = expandEntityReferences;
                this.currentNode = root;
                this.NodeFilter = NodeFilter;
            };
    
            TreeWalker.prototype.parentNode = function () {
                var testNode = this.currentNode;
    
                do {
                    if (
                        testNode !== this.root &&
                        testNode.parentNode &&
                        testNode.parentNode !== this.root
                    ) {
                        testNode = testNode.parentNode;
                    } else {
                        return null;
                    }
                } while (this._getFilteredStatus(testNode) !== this.NodeFilter.FILTER_ACCEPT);
                (testNode) && (this.currentNode = testNode);
    
                return testNode;
            };
    
            TreeWalker.prototype.firstChild = function () {
                var testNode = this.currentNode.firstChild;
    
                while(testNode) {
                    if(this._getFilteredStatus(testNode) === this.NodeFilter.FILTER_ACCEPT) {
                        break;
                    }
                    testNode = testNode.nextSibling;
                }
                (testNode) && (this.currentNode = testNode);
    
                return testNode;
            };
    
            TreeWalker.prototype.lastChild = function () {
                var testNode = this.currentNode.lastChild;
    
                while (testNode) {
                    if(this._getFilteredStatus(testNode) === this.NodeFilter.FILTER_ACCEPT) {
                        break;
                    }
                    testNode = testNode.previousSibling;
                }
                (testNode) && (this.currentNode = testNode);
    
                return testNode;
            };
    
            TreeWalker.prototype.nextNode = function () {
                var testNode = this.currentNode;
    
                while (testNode) {
                    if (testNode.childNodes.length !== 0) {
                        testNode = testNode.firstChild;
                    } else if (testNode.nextSibling) {
                        testNode = testNode.nextSibling;
                    } else {
                        while (testNode) {
                            if (testNode.parentNode && testNode.parentNode !== this.root) {
                                if (testNode.parentNode.nextSibling) {
                                    testNode = testNode.parentNode.nextSibling;
                                    break;
                                } else {
                                    testNode = testNode.parentNode;
                                }
                            }
                            else return null;
                        }
                    }
                    if (testNode && this._getFilteredStatus(testNode) === this.NodeFilter.FILTER_ACCEPT) {
                        break;
                    }
                }
                (testNode) && (this.currentNode = testNode);
    
                return testNode;
            };
    
            TreeWalker.prototype.previousNode = function () {
                var testNode = this.currentNode;
    
                while (testNode) {
                    if (testNode.previousSibling) {
                        testNode = testNode.previousSibling;
                        while (testNode.lastChild) {
                            testNode = testNode.lastChild;
                        }
                    }
                    else {
                        if (testNode.parentNode && testNode.parentNode !== this.root) {
                            testNode = testNode.parentNode;
                        }
                        else testNode = null;
                    }
                    if (testNode && this._getFilteredStatus(testNode) === this.NodeFilter.FILTER_ACCEPT) {
                        break;
                    }
                }
                (testNode) && (this.currentNode = testNode);
    
                return testNode;
            };
    
            TreeWalker.prototype.nextSibling = function () {
                var testNode = this.currentNode;
    
                while(testNode) {
                    (testNode.nextSibling) && (testNode = testNode.nextSibling);
                    if(this._getFilteredStatus(testNode) === this.NodeFilter.FILTER_ACCEPT) {
                        break;
                    }
                }
                (testNode) && (this.currentNode = testNode);
    
                return testNode;
            };
    
            TreeWalker.prototype.previousSibling = function () {
                var testNode = this.currentNode;
    
                while(testNode) {
                    (testNode.previousSibling) && (testNode = testNode.previousSibling);
                    if(this._getFilteredStatus(testNode) == this.NodeFilter.FILTER_ACCEPT) {
                        break;
                    }
                }
                (testNode) && (this.currentNode = testNode);
    
                return testNode;
            };
    
            TreeWalker.prototype._getFilteredStatus = function (node) {
                var mask = ({
                        /* ELEMENT_NODE */ 1: this.NodeFilter.SHOW_ELEMENT,
                        /* ATTRIBUTE_NODE */ 2: this.NodeFilter.SHOW_ATTRIBUTE,
                        /* TEXT_NODE */ 3: this.NodeFilter.SHOW_TEXT,
                        /* CDATA_SECTION_NODE */ 4: this.NodeFilter.SHOW_CDATA_SECTION,
                        /* ENTITY_REFERENCE_NODE */ 5: this.NodeFilter.SHOW_ENTITY_REFERENCE,
                        /* ENTITY_NODE */ 6: this.NodeFilter.SHOW_PROCESSING_INSTRUCTION,
                        /* PROCESSING_INSTRUCTION_NODE */ 7: this.NodeFilter.SHOW_PROCESSING_INSTRUCTION,
                        /* COMMENT_NODE */ 8: this.NodeFilter.SHOW_COMMENT,
                        /* DOCUMENT_NODE */ 9: this.NodeFilter.SHOW_DOCUMENT,
                        /* DOCUMENT_TYPE_NODE */ 10: this.NodeFilter.SHOW_DOCUMENT_TYPE,
                        /* DOCUMENT_FRAGMENT_NODE */ 11: this.NodeFilter.SHOW_DOCUMENT_FRAGMENT,
                        /* NOTATION_NODE */ 12: this.NodeFilter.SHOW_NOTATION
                    })[node.nodeType];
    
                return (
                    (mask && (this.whatToShow & mask) == 0) ?
                        this.NodeFilter.FILTER_REJECT :
                        (this.filter && this.filter.acceptNode) ?
                            this.filter.acceptNode(node) :
                            this.NodeFilter.FILTER_ACCEPT
                );
            };
    
            if (!document.createTreeWalker) {
                document.createTreeWalker = function (root, whatToShow, filter, expandEntityReferences) {
                    return new TreeWalker(root, whatToShow, filter, expandEntityReferences);
                };
            }
    
            window.onload = function () {
                var walker = document.createTreeWalker(document.getElementById('rootNodeDiv'), NodeFilter.SHOW_ELEMENT, null, false);
    
                alert('currentNode: ' + walker.currentNode.id + ': firstChild: '      + walker.firstChild().id);
                alert('currentNode: ' + walker.currentNode.id + ': nextNode: '        + walker.nextNode().id);
                alert('currentNode: ' + walker.currentNode.id + ': lastChild: '       + walker.lastChild().id);
                alert('currentNode: ' + walker.currentNode.id + ': parentNode: '      + walker.parentNode().id);
                alert('currentNode: ' + walker.currentNode.id + ': previousNode: '    + walker.previousNode().id);
                alert('currentNode: ' + walker.currentNode.id + ': nextSibling: '     + walker.nextSibling().id);
                alert('currentNode: ' + walker.currentNode.id + ': previousSibling: ' + walker.previousSibling().id);
            };
        </script>
        <div id="parentNodeDiv">
            <div id="rootNodeDiv">
                <span id="previousNodeDiv"></span>
                <span id="span01">
                    <p id="span01p01">&nbsp;</p>
                    <p id="span01p02">&nbsp;</p>
                </span>
                <span id="span02"></span>
                <span id="span03">
                    <p id="span02p01">&nbsp;</p>
                </span>
                <span id="span04"></span>
                <span id="span05"></span>
            </div>
        </div>
    </body>
    

    【讨论】:

      猜你喜欢
      • 2016-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多