textNode
문서 내의 모든 개체 컬렉션을 가져올 수있는 방법이 있습니까?
getElementsByTagName()
Elements에서는 잘 작동하지만 textNode
s는 Elements가 아닙니다.
업데이트 : 아래의 많은 사람들이 제안하는대로 DOM을 걷는 것으로 이것이 가능하다는 것을 알고 있습니다. 문서의 모든 노드를 살펴 보는 DOM-walker 함수를 작성하는 방법을 알고 있습니다. 나는 그것을 할 수있는 브라우저 네이티브 방법이 있기를 바랐습니다. 결국 <input>
하나의 내장 호출로 모든 s를 얻을 수 있지만 모든 textNode
s를 얻을 수 있다는 것은 조금 이상합니다 .
답변
업데이트 :
1,000 회 이상 6 가지 방법 각각에 대한 몇 가지 기본 성능 테스트를 설명했습니다. getElementsByTagName
가장 빠르지 만 모든 요소를 선택하지 않고 특정 유형의 태그 (내 생각에 p
) 만 선택 하고 firstChild가 텍스트 요소 라고 맹목적으로 가정 하기 때문에 절반 수준의 작업을 수행합니다 . 결함이 거의 없을 수도 있지만 데모 목적으로 성능을 TreeWalker
. 결과를 보려면 jsfiddle에서 직접 테스트를 실행하십시오 .
- TreeWalker 사용
- 사용자 지정 반복 순회
- 사용자 지정 재귀 순회
- Xpath 쿼리
- querySelectorAll
- getElementsByTagName
Text
기본적으로 모든 노드 를 가져올 수있는 방법이 있다고 가정 해 보겠습니다 . node.nodeValue
DOM 노드와 마찬가지로 실제 텍스트를 얻기 위해 각 결과 텍스트 노드를 탐색하고 호출 해야합니다. 따라서 성능 문제는 텍스트 노드를 반복하는 것이 아니라 텍스트가 아닌 모든 노드를 반복하고 유형을 확인하는 것입니다. 나는 (결과에 근거하여) TreeWalker
속도가 빠르지는 getElementsByTagName
않지만 (getElementsByTagName이 장애가있는 경우에도 ) 성능이 똑같이 빠르다고 주장 합니다 .
각 테스트를 1000 번 실행했습니다. 방법 총 ms 평균 ms -------------------------------------------------- document.TreeWalker 301 0.301 반복 트래버 서 769 0.769 재귀 트래버 서 7352 7.352 XPath 쿼리 1849 1.849 querySelectorAll 1725 1.725 getElementsByTagName 212 0.212
각 방법의 출처 :
TreeWalker
function nativeTreeWalker() {
var walker = document.createTreeWalker(
document.body,
NodeFilter.SHOW_TEXT,
null,
false
);
var node;
var textNodes = [];
while(node = walker.nextNode()) {
textNodes.push(node.nodeValue);
}
}
재귀 트리 순회
function customRecursiveTreeWalker() {
var result = [];
(function findTextNodes(current) {
for(var i = 0; i < current.childNodes.length; i++) {
var child = current.childNodes[i];
if(child.nodeType == 3) {
result.push(child.nodeValue);
}
else {
findTextNodes(child);
}
}
})(document.body);
}
반복 트리 순회
function customIterativeTreeWalker() {
var result = [];
var root = document.body;
var node = root.childNodes[0];
while(node != null) {
if(node.nodeType == 3) { /* Fixed a bug here. Thanks @theazureshadow */
result.push(node.nodeValue);
}
if(node.hasChildNodes()) {
node = node.firstChild;
}
else {
while(node.nextSibling == null && node != root) {
node = node.parentNode;
}
node = node.nextSibling;
}
}
}
querySelectorAll
function nativeSelector() {
var elements = document.querySelectorAll("body, body *"); /* Fixed a bug here. Thanks @theazureshadow */
var results = [];
var child;
for(var i = 0; i < elements.length; i++) {
child = elements[i].childNodes[0];
if(elements[i].hasChildNodes() && child.nodeType == 3) {
results.push(child.nodeValue);
}
}
}
getElementsByTagName (핸디캡)
function getElementsByTagName() {
var elements = document.getElementsByTagName("p");
var results = [];
for(var i = 0; i < elements.length; i++) {
results.push(elements[i].childNodes[0].nodeValue);
}
}
XPath
function xpathSelector() {
var xpathResult = document.evaluate(
"//*/text()",
document,
null,
XPathResult.ORDERED_NODE_ITERATOR_TYPE,
null
);
var results = [], res;
while(res = xpathResult.iterateNext()) {
results.push(res.nodeValue); /* Fixed a bug here. Thanks @theazureshadow */
}
}
또한이 토론이 도움이 될 수 있습니다-http: //bytes.com/topic/javascript/answers/153239-how-do-i-get-elements-text-node
답변
Iterator
가장 빠른 TreeWalker 메서드 의 최신 버전은 다음과 같습니다 .
function getTextNodesIterator(el) { // Returns an iterable TreeWalker
const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT);
walker[Symbol.iterator] = () => ({
next() {
const value = walker.nextNode();
return {value, done: !value};
}
});
return walker;
}
용법:
for (const textNode of getTextNodesIterator(document.body)) {
console.log(textNode)
}
더 안전한 버전
반복자를 직접 사용하면 루프 중에 노드를 이동하면 중단 될 수 있습니다. 이것은 더 안전하며 배열을 반환합니다.
function getTextNodes(el) { // Returns an array of Text nodes
const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT);
const nodes = [];
while (walker.nextNode()) {
nodes.push(walker.currentNode);
}
return nodes;
}
답변
특별히 컬렉션을 요청한 것을 알고 있지만 비공식적으로 의미하고 모두 하나의 큰 문자열로 결합되어 있는지 신경 쓰지 않았다면 다음을 사용할 수 있습니다.
var allTextAsString = document.documentElement.textContent || document.documentElement.innerText;
… 첫 번째 항목은 DOM3 표준 접근 방식입니다. 그러나 innerText
이를 지원하는 구현 (최소한 IE 및 Chrome)에서는 스크립트 또는 스타일 태그 콘텐츠를 제외하는 반면 textContent
(Firefox 및 Chrome에서는) 포함 하는 것으로 보입니다 .
답변
document.deepText= function(hoo, fun){
var A= [], tem;
if(hoo){
hoo= hoo.firstChild;
while(hoo!= null){
if(hoo.nodeType== 3){
if(typeof fun== 'function'){
tem= fun(hoo);
if(tem!= undefined) A[A.length]= tem;
}
else A[A.length]= hoo;
}
else A= A.concat(document.deepText(hoo, fun));
hoo= hoo.nextSibling;
}
}
return A;
}
/ * 일부 부모 요소의 모든 하위 텍스트 노드의 배열을 반환하거나 일부 함수를 전달하고 제자리에서 텍스트에 대해 무언가 (찾기 또는 바꾸기 등)를 수행 할 수 있습니다.
이 예제는 본문에서 공백이 아닌 텍스트 노드의 텍스트를 반환합니다.
var A= document.deepText(document.body, function(t){
var tem= t.data;
return /\S/.test(tem)? tem: undefined;
});
alert(A.join('\n'))
* /
검색 및 바꾸기, 강조 표시 등에 편리합니다.
답변
여기에 좀 더 관용적이고 이해하기 쉬운 대안이 있습니다.
function getText(node) {
// recurse into each child node
if (node.hasChildNodes()) {
node.childNodes.forEach(getText);
}
// get content of each non-empty text node
else if (node.nodeType === Node.TEXT_NODE) {
const text = node.textContent.trim();
if (text) {
console.log(text); // do something
}
}
}
답변
var el1 = document.childNodes[0]
function get(node,ob)
{
ob = ob || {};
if(node.childElementCount)
{
ob[node.nodeName] = {}
ob[node.nodeName]["text"] = [];
for(var x = 0; x < node.childNodes.length;x++)
{
if(node.childNodes[x].nodeType == 3)
{
var txt = node.childNodes[x].nodeValue;
ob[node.nodeName]["text"].push(txt)
continue
}
get(node.childNodes[x],ob[node.nodeName])
};
}
else
{
ob[node.nodeName] = (node.childNodes[0] == undefined ? null :node.childNodes[0].nodeValue )
}
return ob
}
var o = get(el1)
console.log(o)
답변
나중에 createTreeWalker
사용할 수 있습니다.
/**
* Get all text nodes under an element
* @param {!Element} el
* @return {Array<!Node>}
*/
function getTextNodes(el) {
const iterator = document.createNodeIterator(el, NodeFilter.SHOW_TEXT);
const textNodes = [];
let currentTextNode;
while ((currentTextNode = iterator.nextNode())) {
textNodes.push(currentTextNode);
}
return textNodes;
}