指定 acceptNode 时 createNodeIterator 在 IE9 中失败
createNodeIterator fails in IE9 when acceptNode is specified
目标
我想遍历 DOM 个文本节点,按它们在 DOM 中的顺序排序。此外,我想通过自定义逻辑过滤节点(例如,检查节点是否在特定元素内)。此外,所有这些都应该以最佳性能完成并在 IE9+ 中工作。
方法
以上所有要求都满足
我不完全理解为什么这些相似的功能没有合并在一起。但是,由于 createTreeWalker()
有更多 API 方法,我已经开始使用它了。
然后我发现根据documentation, the acceptNode
filter function isn't supported in IE9. Therefore I switched over to createNodeIterator
, which hasn't this restriction according to the documentation.
这是我用来遍历元素的代码:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Test</title>
</head>
<body>
<div class="context">
Root first
<div>
Child
</div>
Root second
</div>
<script type="text/javascript">
var treeWalker = document.createNodeIterator(
document.querySelector(".context"),
NodeFilter.SHOW_TEXT,
{
acceptNode: function(){
return NodeFilter.FILTER_ACCEPT;
}
},
false
);
var nodeList = [];
var currentNode;
while (currentNode = treeWalker.nextNode()){
nodeList.push(currentNode);
}
console.log(nodeList);
</script>
</body>
</html>
虽然在这种情况下循环实际上(几乎)什么都不做,但在我的实际应用程序中它确实做了。所以请看这个例子。
问题
问题是以上在 IE9 中不工作。似乎 IE9 也不支持 createNodeIterator
的 acceptNode
过滤器回调 属性。必须 null
才能工作。但是,正如文档所说的那样,它是受支持的,我希望它能正常工作。
我的期望:
实际消息:
问题
这是什么问题,如何解决?请注意,我绝对需要循环。
我认为你真正拥有循环的部分是事情搞砸的地方。我确实理解你想要做什么,但我想出了一种方法,我相信你仍然可以使用它来获得相同的结果:
try{
var treeWalker = document.createNodeIterator(
document.querySelector(".context"),
NodeFilter.SHOW_TEXT,
{ acceptNode: function(node)
{ return NodeFilter.FILTER_ACCEPT; }
},
false
);
//This will help you avoid the loop you currently have on your code, but you wold still need one if you want to have a wrapper task that you want to perform on your treelist items
var nodeList = treeWalker.root.childNodes;
console.log(nodeList [0]);
}catch(e){
console.log(e);
}
//版本 2
var nodeIterator = document.createNodeIterator(
document.body,
NodeFilter.SHOW_ELEMENT,
function(node) {
return node.nodeName.toLowerCase() === 'p' ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT;
},
false
);
var pars = [];
//what you were missing for it to work on IE
var currentNode = "<p></p>";
while (currentNode = nodeIterator.nextNode()) {
console.dir(currentNode); // or console wherever you want
pars.push(currentNode);
}
实际上我在 IE11 中有完全相同的错误。
如果您查看 Document Object Model Level 2 Traversal and Range and more specifically the Appendix C regarding ECMAScript Language Binding 的 W3C 文档,NodeFilter 对象定义如下:
This is an ECMAScript function reference. This method returns a Number. The parameter is a Node object.
因此,如果您更新脚本以传递函数而不是带有键的对象 acceptNode
,您将获得预期的结果。
var treeWalker = document.createNodeIterator(
document.querySelector(".context"),
NodeFilter.SHOW_TEXT,
function(){
return NodeFilter.FILTER_ACCEPT;
},
false
);
Firefox 中的结果将是:
在 Chrome 你会得到:
在 IE 中,您将拥有:
我没有修改你的循环或其他任何东西来获得这些结果,所以我只发布了相关部分。
目标
我想遍历 DOM 个文本节点,按它们在 DOM 中的顺序排序。此外,我想通过自定义逻辑过滤节点(例如,检查节点是否在特定元素内)。此外,所有这些都应该以最佳性能完成并在 IE9+ 中工作。
方法
以上所有要求都满足
我不完全理解为什么这些相似的功能没有合并在一起。但是,由于 createTreeWalker()
有更多 API 方法,我已经开始使用它了。
然后我发现根据documentation, the acceptNode
filter function isn't supported in IE9. Therefore I switched over to createNodeIterator
, which hasn't this restriction according to the documentation.
这是我用来遍历元素的代码:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Test</title>
</head>
<body>
<div class="context">
Root first
<div>
Child
</div>
Root second
</div>
<script type="text/javascript">
var treeWalker = document.createNodeIterator(
document.querySelector(".context"),
NodeFilter.SHOW_TEXT,
{
acceptNode: function(){
return NodeFilter.FILTER_ACCEPT;
}
},
false
);
var nodeList = [];
var currentNode;
while (currentNode = treeWalker.nextNode()){
nodeList.push(currentNode);
}
console.log(nodeList);
</script>
</body>
</html>
虽然在这种情况下循环实际上(几乎)什么都不做,但在我的实际应用程序中它确实做了。所以请看这个例子。
问题
问题是以上在 IE9 中不工作。似乎 IE9 也不支持 createNodeIterator
的 acceptNode
过滤器回调 属性。必须 null
才能工作。但是,正如文档所说的那样,它是受支持的,我希望它能正常工作。
我的期望:
实际消息:
问题
这是什么问题,如何解决?请注意,我绝对需要循环。
我认为你真正拥有循环的部分是事情搞砸的地方。我确实理解你想要做什么,但我想出了一种方法,我相信你仍然可以使用它来获得相同的结果:
try{
var treeWalker = document.createNodeIterator(
document.querySelector(".context"),
NodeFilter.SHOW_TEXT,
{ acceptNode: function(node)
{ return NodeFilter.FILTER_ACCEPT; }
},
false
);
//This will help you avoid the loop you currently have on your code, but you wold still need one if you want to have a wrapper task that you want to perform on your treelist items
var nodeList = treeWalker.root.childNodes;
console.log(nodeList [0]);
}catch(e){
console.log(e);
}
//版本 2
var nodeIterator = document.createNodeIterator(
document.body,
NodeFilter.SHOW_ELEMENT,
function(node) {
return node.nodeName.toLowerCase() === 'p' ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT;
},
false
);
var pars = [];
//what you were missing for it to work on IE
var currentNode = "<p></p>";
while (currentNode = nodeIterator.nextNode()) {
console.dir(currentNode); // or console wherever you want
pars.push(currentNode);
}
实际上我在 IE11 中有完全相同的错误。
如果您查看 Document Object Model Level 2 Traversal and Range and more specifically the Appendix C regarding ECMAScript Language Binding 的 W3C 文档,NodeFilter 对象定义如下:
This is an ECMAScript function reference. This method returns a Number. The parameter is a Node object.
因此,如果您更新脚本以传递函数而不是带有键的对象 acceptNode
,您将获得预期的结果。
var treeWalker = document.createNodeIterator(
document.querySelector(".context"),
NodeFilter.SHOW_TEXT,
function(){
return NodeFilter.FILTER_ACCEPT;
},
false
);
Firefox 中的结果将是:
在 Chrome 你会得到:
在 IE 中,您将拥有:
我没有修改你的循环或其他任何东西来获得这些结果,所以我只发布了相关部分。