16、DOM操作全解析

DOM操作全解析

1. 常用函数介绍

在进行DOM操作时,有几个常用的函数能极大地提高开发效率。
- $() 函数 :它是 document.getElementById() 的特殊封装。与 document.getElementById() 不同的是, $() 可以接受多个参数,并返回包含所有请求元素的数组。如果参数不是字符串,会直接传递。例如:

// <p id="one">One</p>
// <p id="two">Two</p>
$('one').toString();
// => '[object HTMLParagraphElement]'
$('one','two').toString();
// => [object P],[object P]
$($('one')).toString();
// => [object HTMLParagraphElement]
  • $F() 函数 :用于返回任何字段输入控件(如文本框或下拉列表)的值。 element 可以是ID字符串或元素对象本身。示例如下:
// <input type="text" id="userName" value="Joe Doe">
// <select id="state">
//   <option value="NY">New York</option>
//   <option value="CA" selected="selected">California</option>
// </select>
$F('userName');
// => "Joe Doe"
$F('state');
// => "CA"
2. 选择器

Selector 类及其伴随的 $$() 方法允许通过CSS选择器引用页面元素,使用与CSS文件中相同的语法。 $$() 方法接受一个或多个CSS选择器表达式,并返回匹配的元素。
- 示例代码

$$('form#foo input[type=text]').each(function(input) {
  input.setStyle({color: 'red'});
});

上述代码选择了ID为 foo 的表单元素下的所有文本字段,并将它们的颜色设置为红色。
- 其他可能的表达式
- 按标签名(包括通配符): $$('strong') $$('*')
- 按ID和类: $('#foo') $$('.bar')
- 按标签、ID和类的组合: $$('strong#foo') $$('string.bar')
- 按祖先元素: $$('#foo strong *') $$('strong#foo span')
- 按属性存在性: $$('h1[class]')
- 按属性值和否定值: $$('a[href="#"]') $$('a[href!=#]')
- 按空格分隔的属性值: $$('a[class~="internal"]')
- 按连字符分隔的属性值: $$('*[xml:lang|="es"]')
- 按多个属性条件: $$('a[class~=external][href="#"]')
- 组合多个表达式: $('#foo', '#bar')

Selector 类还提供了一些方法:
| 方法 | 描述 |
| ---- | ---- |
| initialize( expression ) | 为表达式创建一个新的选择器实例 |
| findElements([ scope ]) | 返回所有匹配选择器表达式的元素,这些元素是 scope 元素的子元素(默认为整个文档) |
| match( element ) | 如果元素匹配选择器表达式,则返回 true |
| toString( ) | 返回选择器表达式的字符串表示 |
| matchElements( elements , expression ) | 静态方法,返回匹配表达式的元素子集 |
| findElement( elements , expression [, index ]) | 静态方法,返回匹配表达式的第一个元素。如果提供了 index ,则返回第 n 个匹配元素 |
| findChildElements( element , expressions ) | 静态方法,返回从 element 派生的、匹配 expressions 数组中任何表达式的元素数组 |

以下是一些使用示例:

// Create a Selector instance
fooFinder = new Selector('.foo');

// Find all elements in the document with the class 'foo'
fooFinder.findElements();
// Find all elements within the 'container' element with the class 'foo'
fooFinder.findElements($('container'));
// Determine whether the 'bar' element has the class 'foo'
fooFinder.match($('bar'));
// Find all elements with class 'foo' from the descendants of 'container'
Selector.matchElements($('container').descendants(), '.foo');
// Find the first element with the class 'foo' from the descendants of 'container'
Selector.findElement($('container').descendants(), '.foo');
// Find the second element with the class 'foo' from the descendants of 'container'
Selector.findElement($('container').descendants(), '.foo', 1);
// Find all elements with the class 'foo' within 'container'
Selector.findChildElements($('container'), ['.foo']);
// Find all elements with the class 'foo' or the class 'bar' within 'container'
Selector.findChildElements($('container'), ['.foo', '.bar']);

另外, document.getElementsByClassName(className [, parentElement]) 方法返回与CSS类 className 关联的所有元素。如果未提供 parentElement ,则会搜索整个文档主体。

3. 元素方法

提供了用于操作页面元素的方法,这些方法可以通过两种方式访问。
- 作为函数访问

Element.toggle('target');
var myElement = $('target2');
Element.update(myElement, 'Hello');

上述代码切换了ID为 target 的元素的可见性,并将 myElement 元素的内容替换为 Hello
- 作为页面元素对象的方法直接访问 :每当通过Prototype的 $() $$() 函数引用元素时, Element.Methods 中的所有方法都会复制到元素对象中。示例如下:

$('target').toggle();
var myElement = $('target2');
myElement.update('Hello');

许多方法会返回它们操作的元素,从而实现方便的链式调用。例如:

$('target').update('Hello').addClassName('big').show();

以下是一些常用的元素方法:
| 方法 | 描述 |
| ---- | ---- |
| hide( element ) | 通过将元素的显示样式设置为 none 来隐藏元素,返回元素 |
| show( element ) | 通过将元素的显示样式重置为空来显示元素,返回元素 |
| toggle( element ) | 切换元素的可见性,返回元素 |
| visible( element ) | 返回一个布尔值,指示元素是否可见 |
| empty( element ) | 返回一个布尔值,指示元素的标签是否为空(或只有空白) |
| remove( element ) | 从文档中移除元素,返回元素 |
| update( element , html ) | 用 html 替换元素的内部HTML。如果 html 包含 <script> 块,它们将不包含在内,但会被评估,返回元素 |
| replace( element , html ) | 跨浏览器实现“outerHTML”属性,用 html 替换整个元素(包括其开始和结束标签),返回元素 |
| classNames( element ) | 返回一个表示与元素关联的CSS类名的 Element.ClassNames 对象 |
| hasClassName( element , className ) | 如果元素的类名中包含 className ,则返回 true |
| addClassName( element , className ) | 将 className 添加到与元素关联的CSS类名列表中,返回元素 |
| removeClassName( element , className ) | 从与元素关联的CSS类名列表中移除 className ,返回元素 |
| getStyle( element , cssProperty ) | 返回元素中CSS属性 cssProperty 的值(格式为 prop-name propName ),如果不存在则返回 null |
| setStyle( element , cssPropertyHash ) | 根据 cssPropertyHash 哈希中的值设置元素的CSS属性值,返回元素 |
| readAttribute( element , name ) | 返回元素名为 name 的属性的值 |
| getDimensions( element ) | 返回元素的尺寸,返回值是一个包含 height width 属性的对象 |
| getHeight( element ) | 返回元素的 offsetHeight |
| makeClipping( element ) | 将元素的溢出样式设置为 hidden ,保存先前的值,返回元素 |
| undoClipping( element ) | 将元素的溢出样式恢复到先前的状态,返回元素 |
| makePositioned( element ) | 将元素的位置样式设置为 relative ,返回元素 |
| undoPositioned( element ) | 将元素的位置样式设置为空,返回元素 |
| scrollTo( element ) | 将窗口滚动到元素的位置,返回元素 |
| cleanWhitespace( element ) | 移除元素的任何空白文本节点子元素,返回元素 |
| ancestors( element ) | 返回元素的所有祖先元素的数组 |
| descendants( element ) | 返回元素的所有后代元素的数组 |
| immediateDescendants(element) | 返回元素的不包含文本节点的子节点数组 |
| siblings( element ) | 返回元素的所有兄弟元素的数组 |
| previousSiblings( element ) | 返回元素在树中之前的所有兄弟元素的数组 |
| nextSiblings( element ) | 返回元素在树中之后的所有兄弟元素的数组 |
| up( element [, expression ][, index ]) | 返回元素的第一个祖先元素,可选择匹配CSS选择器表达式。如果提供了 index ,则返回第 n 个匹配元素 |
| down( element [, expression ][, index ]) | 返回元素的第一个子元素,可选择匹配CSS选择器表达式。如果提供了 index ,则返回第 n 个匹配元素 |
| previous( element [, expression ][, index ]) | 返回元素的第一个前一个兄弟元素,可选择匹配CSS选择器表达式。如果提供了 index ,则返回第 n 个匹配元素 |
| next( element [, expression ][, index ]) | 返回元素的第一个下一个兄弟元素,可选择匹配CSS选择器表达式。如果提供了 index ,则返回第 n 个匹配元素 |
| getElementsByClassName( element, className ) | 返回元素的所有具有类 className 的后代元素的数组 |
| getElementsBySelector( element, expression1[, expression2 [...] ) | 返回元素的所有匹配任何给定CSS选择器表达式的后代元素的数组 |
| recursivelyCollect( element , property ) | 递归返回与元素根据 property 相关的所有元素的数组 |
| match( element, selector ) | 接受单个CSS选择器表达式(或 Selector 实例),如果匹配元素则返回 true |
| childOf( element, ancestor ) | 如果元素是 ancestor 的后代,则返回 true |
| observe( element, name, observer [ , useCapture ]) | 为元素添加一个事件处理函数 observer ,用于处理名为 name 的事件(如 click load 等)。如果 useCapture true ,则在捕获阶段处理事件;如果为 false ,则在冒泡阶段处理事件,返回元素 |
| stopObserving( element, name, observer [ , useCapture ]) | 从元素中移除名为 name 的事件处理程序。 observer 是函数引用(不是匿名函数)。如果 useCapture true ,则在捕获阶段处理事件;如果为 false ,则在冒泡阶段处理事件,返回元素 |
| hasAttribute( element , attribute ) | 如果元素具有名为 attribute 的属性,则返回 true |
| inspect( element ) | 返回元素的字符串表示,用于调试,包括其名称、ID和类 |

以下是一个简单的mermaid流程图,展示了元素方法的调用流程:

graph LR
    A[获取元素] --> B[调用元素方法]
    B --> C{是否链式调用}
    C -- 是 --> B
    C -- 否 --> D[结束操作]
4. 表单相关操作
  • 表单对象方法 Form 对象提供了专门用于处理表单的额外元素方法。这些方法会自动添加到通过 $() $$() 访问的元素中,但仅当元素是表单时才会添加。
    • serialize( element ) :返回元素的字段名和值的URL格式字符串。
    • serializeElements( elements ) :返回元素的字段名和值的URL格式字符串。
    • findFirstElement( element ) :返回元素中的第一个启用的字段元素。
    • getElements( element ) :返回包含元素中所有输入字段的数组。
    • getInputs( element [, typeName [, name ]]) :返回包含元素中所有 <input> 元素的数组。可选择根据元素的 typeName name 属性过滤列表。
    • disable( element ) :禁用表单中的所有输入字段,返回元素。
    • enable( element ) :启用表单中的所有输入字段,返回元素。
    • focusFirstElement( element ) :激活表单中第一个可见、启用的输入字段,返回元素。
    • reset( element ) :将表单重置为其默认状态,返回元素。

示例代码:

// <form id="target"><input type="text" name="foo" value="bar" /></form>
Form.serialize('target'); // => "foo=bar"
$('target').serializeElements(); // => "foo=bar"
$('target').findFirstElement();
$('target').getElements();
$('target').getInputs();
$('target').getInputs('text');
$('target').getInputs('text', 'foo');
$('target').disable();
$('target').enable();
$('target').focusFirstElement();
$('target').reset();
  • 表单元素对象方法 Form.Element 对象(别名 Field )提供了专门用于处理表单字段的额外元素方法。这些方法会自动添加到通过 $() $$() 访问的元素中,但仅当元素是表单字段时才会添加。
    • serialize( element ) :返回元素的 name=value 字符串。
    • getValue( element ) :返回元素的值。
    • clear( element ) :清除元素的值,返回元素。
    • present( element ) :如果元素包含非空值,则返回 true
    • focus( element ) :将输入焦点移动到元素,返回元素。
    • select( element ) :选择元素中支持文本选择的值,返回元素。
    • activate( element ) :移动焦点并选择元素中支持文本选择的值,返回元素。
    • disable( element ) :禁用元素的输入,返回元素。
    • enable( element ) :启用元素的输入,返回元素。

示例代码:

// <input id="target" type="text" name="foo" value="bar" />
$('target').serialize(); // => "foo=bar"
$('target').getValue(); // => "bar"
$('target').clear();
$('target').present(); // => true
$('target').focus();
$('target').select();
$('target').activate();
$('target').disable();
$('target').enable();
5. Element.ClassNames类

Element.ClassNames 类代表与元素关联的CSS类名集合,提供了一系列操作类名的方法。
| 方法 | 描述 |
| ---- | ---- |
| initialize( element ) | 创建一个表示元素CSS类名的 Element.ClassNames 对象 |
| add( className ) | 将 className 包含在与元素关联的类名列表中 |
| remove( className ) | 从与元素关联的CSS类名列表中移除 className |
| set( className ) | 将元素与 className 关联,并移除元素的任何其他类名 |

此外, Element.ClassNames 还扩展了 Enumerable 方法,方便对类名进行遍历等操作。以下是使用示例:

// 创建Element.ClassNames对象
var classNamesObj = new Element.ClassNames($('target'));
// 添加类名
classNamesObj.add('newClass');
// 移除类名
classNamesObj.remove('oldClass');
// 设置类名
classNamesObj.set('singleClass');
6. 动态内容插入

Abstract.Insertion 用作其他提供动态内容插入的类的基类。它有几个重要的属性:
- adjacency :一个字符串,指定内容相对于给定元素的放置位置,可能的值为 beforeBegin afterBegin beforeEnd afterEnd
- element :插入操作将相对于其进行的元素对象。
- content :要插入的内容。

基于 Abstract.Insertion ,有以下几个具体的插入类:
| 类名 | 描述 |
| ---- | ---- |
| Insertion.Before | 继承自 Abstract.Insertion ,初始化时将内容插入到元素之前 |
| Insertion.Top | 继承自 Abstract.Insertion ,初始化时将内容插入到元素下的第一个子元素位置,即元素的开始标签之后 |
| Insertion.Bottom | 继承自 Abstract.Insertion ,初始化时将内容插入到元素下的最后一个子元素位置,即元素的结束标签之前 |
| Insertion.After | 继承自 Abstract.Insertion ,初始化时将内容插入到元素的结束标签之后 |

以下是使用示例:

// <span id="name">Douglas</span>
new Insertion.Before('name', 'Hello, ');
new Insertion.Top('name', 'Scott ');
new Insertion.Bottom('name', ' Raymond');
new Insertion.After('name', '.');

下面是一个mermaid流程图,展示动态内容插入的流程:

graph LR
    A[创建插入对象] --> B{选择插入位置}
    B -- beforeBegin --> C[插入到元素之前]
    B -- afterBegin --> D[插入到元素开始标签后]
    B -- beforeEnd --> E[插入到元素结束标签前]
    B -- afterEnd --> F[插入到元素之后]
7. 元素定位

Position 对象提供了许多有助于元素定位的函数。
| 方法 | 描述 |
| ---- | ---- |
| prepare( ) | 调整 deltaX deltaY 属性以适应滚动位置的变化。在页面滚动后调用 withinIncludingScrolloffset 之前,记得调用此方法 |
| realOffset( element ) | 返回一个数组 [left, top] ,包含元素的滚动偏移量,包括影响它的任何滚动偏移量 |
| cumulativeOffset( element ) | 返回一个数组 [left, top] ,包含元素及其所有祖先元素的定位偏移量之和 |
| positionedOffset( element ) | 返回一个数组 [left, top] ,包含元素及其祖先元素到第一个具有绝对或相对位置的祖先元素的定位偏移量之和 |
| offsetParent( element ) | 返回元素最近的具有非静态位置样式的祖先元素 |
| within( element , x , y ) | 测试给定的点坐标 x y 是否在元素的边界矩形内 |
| withinIncludingScrolloffsets( element , x , y ) | 测试给定的点坐标 x y 是否在元素的边界矩形内,考虑滚动偏移量 |
| overlap( mode , element ) | mode 应为 vertical horizontal 。在调用此方法之前需要先调用 within() 。此方法将返回一个介于0.0和1.0之间的小数,表示坐标在元素上重叠的比例 |
| page( element ) | 返回一个数组 [left, top] ,包含元素相对于视口的偏移量 |
| clone( source , target ) | 将元素 target 的大小和位置调整为与 source 相同 |
| absolutize( element ) | 将元素的位置样式设置为绝对,并保留其位置和大小 |
| relativize( element ) | 将元素的位置样式设置为相对,并保留其位置和大小 |

以下是使用示例:

// 调整滚动偏移量
Position.prepare();
// 获取元素的滚动偏移量
var offset = Position.realOffset($('target'));
// 测试点是否在元素内
var isWithin = Position.within($('target'), 100, 100);
// 克隆元素位置
Position.clone($('source'), $('target'));
8. 表单观察者

表单观察者用于监测元素属性的变化,主要有以下几种类型。

8.1 抽象定时观察者

Abstract.TimedObserver 类用作其他监测元素属性变化的类的基类。
| 属性/方法 | 描述 |
| ---- | ---- |
| initialize( element , frequency , callback ) | 创建一个对象,每 frequency 秒监测一次 element ,当元素发生变化时调用 callback |
| element | 被监测的元素对象 |
| frequency | 检查之间的间隔(以秒为单位) |
| callback | 每当元素发生变化时调用的函数,符合 Function ( Object , String ) 格式,将接收元素对象和新值 |
| lastValue | 元素中最后一次验证的值的字符串 |

8.2 表单元素观察者

Form.Element.Observer Abstract.TimedObserver 的实现,用于监测表单输入元素的值。当要监测的元素没有暴露报告值变化的事件时使用此类。

// 监测表单元素值的变化
var observer = new Form.Element.Observer('inputId', 2, function(element, value) {
    console.log('Value changed to: ' + value);
});
8.3 表单观察者

Form.Observer Abstract.TimedObserver 的实现,用于监测表单中任何输入元素的任何变化。当要监测的表单包含没有暴露报告值变化事件的元素时使用此类。

// 监测表单数据的变化
var formObserver = new Form.Observer('formId', 3, function(form, value) {
    console.log('Form data changed: ' + value);
});
8.4 抽象事件观察者

Abstract.EventObserver 类用作其他在元素发生值变化事件时执行回调函数的类的基类。多个观察者可以绑定到同一个元素,回调函数将按分配给元素的顺序执行。触发事件对于单选按钮和复选框是 onclick ,对于文本框和列表框/下拉框通常是 onchange
| 属性/方法 | 描述 |
| ---- | ---- |
| initialize( element , callback ) | 创建一个对象,监测 element ,当事件发生时调用 callback |
| element | 被监测的元素对象 |
| callback | 每当元素发生变化时调用的函数,符合 Function ( Object , String ) 格式,将接收元素对象和新值 |
| lastValue | 元素中最后一次验证的值的字符串 |

8.5 表单元素事件观察者和表单事件观察者

Form.Element.EventObserver Form.EventObserver 分别用于监测表单元素和表单的数据变化,利用元素的事件来检测值的变化。如果表单包含没有暴露任何报告变化事件的元素,则使用 Form.Observer

// 表单元素事件观察者
var elementEventObserver = new Form.Element.EventObserver('inputId', function(element, value) {
    console.log('Element value changed: ' + value);
});
// 表单事件观察者
var formEventObserver = new Form.EventObserver('formId', function(form, value) {
    console.log('Form data changed via event: ' + value);
});

下面是一个mermaid流程图,展示表单观察者的工作流程:

graph LR
    A[创建观察者对象] --> B{选择观察者类型}
    B -- 表单元素观察者 --> C[监测表单元素值变化]
    B -- 表单观察者 --> D[监测表单数据变化]
    B -- 表单元素事件观察者 --> E[利用事件监测表单元素值变化]
    B -- 表单事件观察者 --> F[利用事件监测表单数据变化]
    C --> G[值变化时调用回调]
    D --> G
    E --> G
    F --> G

综上所述,通过这些丰富的DOM操作方法和类,开发者可以方便地对页面元素进行各种操作,包括元素的选择、样式修改、内容插入、定位以及表单数据的监测等,大大提高了开发效率和页面交互性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值