
前面我们学习了模型的基础知识,今天我们来看看模型另一个特点:模型位置的迭代。也就是TeeeWalker这个类用来在模型的位置之间迭代访问模型的节点。
TreeWalker属性
boundaries : Range
迭代器边界
这个属性用于指定迭代器在文档的哪个范围内迭代访问文档的Item。当迭代器在边界的末端“向前”行走或在边界的起点“向后”行走时,返回 { done: true }。
direction : 'backward' | 'forward'
行走方向。默认“前进”。
ignoreElementEnd : Boolean
指示迭代器是否应忽略 elementEnd 标记的标志。如果选项为 true,walker 将不会返回起始位置的父节点。如果此选项为真,则每个元素将返回一次,而如果选项为假,则它们可能会返回两次:对于“elementStart”和“elementEnd”。
position : Position
迭代器位置。这始终是静态位置,即使初始位置是实时位置。如果未定义起始位置,则位置取决于方向。如果方向是“向前”,则位置从开头开始,当方向为“向后”时,位置从结尾开始。
shallow : Boolean
指示迭代器是否为输入元素的标志。如果迭代器是浅子节点,则任何被迭代节点的子节点都不会与 elementEnd 标签一起返回。
singleChracters : Boolean
指示是否应将具有相同属性的所有连续字符作为一个 TextProxy (true) 或一个一个 (false) 返回的标志。
TreeWalker方法
首先是构造器方法,这个方法其实就是将属性通过构造器传入TreeWalker对象
Symbol.iterator() → Iterable.<TreeWalkerValue>
这个方法其实是最奇怪的方法吧,没见过这样写法的。不要着急,参考可迭代协议和迭代器协议,我们可以知道,如果一个对象是可迭代的,那么这个对象必须实现@@iterator
方法,这意味着对象(或者它原型链上的某个对象)必须有一个键为 @@iterator
的属性,可通过常量 Symbol.iterator
访问该属性:
这个属性的特点是:
[Symbol.iterator] | 一个无参数的函数,其返回值为一个符合迭代器协议的对象。 |
所以我们理解了为啥TreeWalker有这个方法,其实就是实现可迭代协议。这个方法的具体实现如下
Symbol.iterator ]() {
return this;
}
这个函数返回的是this,即这个对象本身。因为这个对象应该实现迭代器协议
实现迭代器协议就是需要有一个next方法
next() → TreeWalkerValue
所以这个方法不难理解,就是为了实现迭代器协议
skip(skip)
只要回调函数返回 true,就在跳过值的方向上移动位置。其实就是有些位置的值不处理,直接跳过。
我们再来看看TreeWalkerValue
这个对象就是每次迭代的时候处理并返回的对象,它有五个属性
item : Item
TreeWalker 新旧位置之间的项目。
length : Number
项目的长度。对于'elementStart',它是1。对于'text',它是文本的长度。对于“elementEnd”,它是未定义的
nextPosition : Position
迭代器的下一个位置。
前向迭代:对于“elementStart”,它是元素内的第一个位置。对于所有其他类型,它是项目之后的位置。
向后迭代:对于'elementEnd',它是元素内的最后一个位置。对于所有其他类型,它是项目之前的位置。
previousPosition : Position
迭代器的先前位置。
前向迭代:对于'elementEnd',它是元素内的最后一个位置。对于所有其他类型,它是项目之前的位置。
向后迭代:对于'elementStart',它是元素内的第一个位置。对于所有其他类型,它是项目之后的位置。
type : TreeWalkerValueType
'elementStart' | 'elementEnd' | 'text'
TreeWalker 执行的步骤的类型。可能的值:'elementStart' 如果 walker 在节点的开头,'elementEnd' 如果 walker 在节点的末尾,或者'text' 如果 walker 遍历文本。
好了,有了以上这个类之后,我们就可以遍历模型文档的节点,然后对节点做一些操作,比如属性操作等。
总结:
1、理解并学习了TreeWalker的迭代原理
2、知道如何通过迭代器操作模型文档
3、理解并学习了可迭代协议和迭代器协议