在JavaScript中实现富文本编辑器时,我需要对选定范围内的每个文本节点进行一些更改。 Range对象提供了用于获取选定范围的startContainerendContainerstartOffsetendOffset的接口(interface)。如何遍历之间的每个DOM节点?

var selection = window.getSelection();
var range = selection.getRange(0);
// How can I iterate over every node within the range?

最佳答案

如建议的那样,您可以使用NodeIterator进入range.commonAncestorContainer

这是一个片段:

var _iterator = document.createNodeIterator(
    range.commonAncestorContainer,
    NodeFilter.SHOW_ALL, // pre-filter
    {
        // custom filter
        acceptNode: function (node) {
            return NodeFilter.FILTER_ACCEPT;
        }
    }
);

var _nodes = [];
while (_iterator.nextNode()) {
    if (_nodes.length === 0 && _iterator.referenceNode !== range.startContainer) continue;
    _nodes.push(_iterator.referenceNode);
    if (_iterator.referenceNode === range.endContainer) break;
}

您应该使用NodeFilter.SHOW_ALL,因为您的范围可以包含多个nodeTypes。如果知道选择的内容,则可以检查this reference以正确选择NodeFilter

编辑:我也想指出document.createTreeWalker()

关键区别在于document.createTreeWalker()允许您的acceptNode过滤器返回具有真正差异的NodeFilter.FILTER_REJECTNodeFilter.FILTER_SKIP

NodeFilter docs引用:



PS:NodeFilter.FILTER_REJECTNodeFilter.acceptNode()文档不正确。

10-06 11:53