textNode문서 내의 모든 개체 컬렉션을 가져올 수있는 방법이 있습니까?
getElementsByTagName()Elements에서는 잘 작동하지만 textNodes는 Elements가 아닙니다.
업데이트 : 아래의 많은 사람들이 제안하는대로 DOM을 걷는 것으로 이것이 가능하다는 것을 알고 있습니다. 문서의 모든 노드를 살펴 보는 DOM-walker 함수를 작성하는 방법을 알고 있습니다. 나는 그것을 할 수있는 브라우저 네이티브 방법이 있기를 바랐습니다. 결국 <input>하나의 내장 호출로 모든 s를 얻을 수 있지만 모든 textNodes를 얻을 수 있다는 것은 조금 이상합니다 .
답변
업데이트 :
1,000 회 이상 6 가지 방법 각각에 대한 몇 가지 기본 성능 테스트를 설명했습니다. getElementsByTagName가장 빠르지 만 모든 요소를 선택하지 않고 특정 유형의 태그 (내 생각에 p) 만 선택 하고 firstChild가 텍스트 요소 라고 맹목적으로 가정 하기 때문에 절반 수준의 작업을 수행합니다 . 결함이 거의 없을 수도 있지만 데모 목적으로 성능을 TreeWalker. 결과를 보려면 jsfiddle에서 직접 테스트를 실행하십시오 .
- TreeWalker 사용
- 사용자 지정 반복 순회
- 사용자 지정 재귀 순회
- Xpath 쿼리
- querySelectorAll
- getElementsByTagName
Text기본적으로 모든 노드 를 가져올 수있는 방법이 있다고 가정 해 보겠습니다 . node.nodeValueDOM 노드와 마찬가지로 실제 텍스트를 얻기 위해 각 결과 텍스트 노드를 탐색하고 호출 해야합니다. 따라서 성능 문제는 텍스트 노드를 반복하는 것이 아니라 텍스트가 아닌 모든 노드를 반복하고 유형을 확인하는 것입니다. 나는 (결과에 근거하여) 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;
}
