我只想将一些jQuery方法映射到其正常的Javascript DOM方法;将jQuery转换为常规Javascript映射
例如
prev()
next()
before()
after()
如果您可以将jQuery/Javascript映射到类似的DOM操作方法,那将会非常好。
我只想将一些jQuery方法映射到其正常的Javascript DOM方法;将jQuery转换为常规Javascript映射
例如
prev()
next()
before()
after()
如果您可以将jQuery/Javascript映射到类似的DOM操作方法,那将会非常好。
这些jQuery方法都没有在基于纯DOM的JS中精确的1对1模拟。如果他们这样做了,那么jQuery就不需要实现自己的方法来完成这些任务。
您可以使用elem.previousSibling
和elem.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的技术 - 通过这样做很容易打破对象上的对象循环。
至于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让生活变得更简单。没有一个很好的理由,不要重新发明轮子。
很好的答案。 +1 – Matt
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)et。人。是? – cwallenpoole
+1请注意,“之后”可以通过使用“insertBefore”(如上所述)或者在父元素上使用“appendChild”来实现,以便在最后一个同级之后添加内容。 – maerics
@cwallenpoole - 那是正确的。 – ShankarSangoli
以下是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"> </p>
<p id="span01p02"> </p>
</span>
<span id="span02"></span>
<span id="span03">
<p id="span02p01"> </p>
</span>
<span id="span04"></span>
<span id="span05"></span>
</div>
</div>
</body>
你为什么不只是看jQuery的来源? – jondavidjohn
(其来源是https://github.com/jquery/jquery/blob/master/src/transing。js,但是它的确是一个大脑弯曲者,并且其声明仍然坚定地“jQuery”,通过本地DOM方法)。 – Matt
完整功能中的方法?例如。 'prev'和'next'带选择器... –