dart:html
使用 dart:html 库来编程浏览器,操作 DOM 中的对象和元素,以及访问 HTML5 API。DOM 代表 文档对象模型,它描述了 HTML 页面的层次结构。
dart:html
的其他常用用途包括操作样式(CSS)、使用 HTTP 请求获取数据以及使用 WebSockets 交换数据。HTML5(和 dart:html
)还有许多本节未涵盖的其他 API。只有 Web 应用可以使用 dart:html
,命令行应用不能使用。
要在您的 Web 应用中使用 HTML 库,请导入 dart:html
:
import 'dart:html';
操作 DOM
#要使用 DOM,您需要了解 窗口、 文档 、元素 和 节点。
Window 对象代表 Web 浏览器的实际窗口。每个 Window 都有一个 Document 对象,它指向当前加载的文档。Window 对象还可以访问各种 API,例如 IndexedDB(用于存储数据)、requestAnimationFrame(用于动画)等等。在选项卡式浏览器中,每个选项卡都有自己的 Window 对象。
使用 Document 对象,您可以在文档中创建和操作 Element 对象。请注意,文档本身就是一个元素,可以被操作。
DOM 模拟一个 Nodes 树。这些节点通常是元素,但它们也可以是属性、文本、注释和其他 DOM 类型。除根节点(没有父节点)外,DOM 中的每个节点都有一个父节点,并且可能有多个子节点。
查找元素
#要操作元素,您首先需要一个代表它的对象。您可以使用查询获取此对象。
使用顶级函数 querySelector()
和 querySelectorAll()
查找一个或多个元素。您可以按 ID、类、标签、名称或这些的任意组合进行查询。 CSS 选择器规范指南 定义了选择器的格式,例如使用 # 前缀指定 ID,使用句点 (.) 指定类。
querySelector()
函数返回与选择器匹配的第一个元素,而 querySelectorAll()
返回与选择器匹配的元素集合。
// 按 ID (an-id) 查找元素。
Element idElement = querySelector('#an-id')!;
// 按类 (a-class) 查找元素。
Element classElement = querySelector('.a-class')!;
// 查找所有带有标签 (<div>) 的元素。
List<Element> divElements = querySelectorAll('div');
// 查找所有文本输入。
List<Element> textInputElements = querySelectorAll(
'input[type="text"]',
);
// 查找 ID 为 'id' 的元素内部 <p> 元素中所有具有 CSS 类 'class' 的元素。
List<Element> specialParagraphElements = querySelectorAll('#id p.class');
操作元素
#您可以使用属性来更改元素的状态。Node 及其子类型 Element 定义了所有元素都具有的属性。例如,所有元素都具有 classes
、 hidden
、 id
、 style
和 title
属性,您可以使用这些属性来设置状态。Element 的子类定义了其他属性,例如 AnchorElement 的 href
属性。
考虑一下在 HTML 中指定锚元素的示例:
<a id="example" href="/another/example">link text</a>
此 <a>
标签指定一个具有 href
属性和文本节点(可通过 text
属性访问)的元素,该文本节点包含字符串“link text”。要更改链接指向的 URL,可以使用 AnchorElement 的 href
属性:
var anchor = querySelector('#example') as AnchorElement;
anchor.href = 'https://dart.dev';
通常需要在多个元素上设置属性。例如,以下代码设置所有具有“mac”、“win”或“linux”类的元素的 hidden
属性。将 hidden
属性设置为 true 与向 CSS 添加 display: none
的效果相同。
<!-- 在 HTML 中: -->
<p>
<span class="linux">Linux 的文字</span>
<span class="macos">Mac 的文字</span>
<span class="windows">Windows 的文字</span>
</p>
// 在 Dart 中:
const osList = ['macos', 'windows', 'linux'];
final userOs = determineUserOs();
// 对于每个可能的 OS...
for (final os in osList) {
// 与用户 OS 匹配?
bool shouldShow = (os == userOs);
// 查找所有具有 class=os 的元素。例如,如果
// os == 'windows',则调用 querySelectorAll('.windows')
// 以查找所有具有类“windows”的元素。
// 请注意,'.$os' 使用字符串插值。
for (final elem in querySelectorAll('.$os')) {
elem.hidden = !shouldShow; // 显示或隐藏。
}
}
当合适的属性不可用或不方便时,您可以使用 Element 的 attributes
属性。此属性是一个 Map<String, String>
,其中键是属性名称。有关属性名称及其含义的列表,请参阅 MDN 属性页面 。以下是如何设置属性值的示例:
elem.attributes['someAttribute'] = 'someValue';
创建元素
#您可以通过创建新元素并将它们附加到 DOM 来添加到现有的 HTML 页面。以下是如何创建段落(<p>)元素的示例:
var elem = ParagraphElement();
elem.text = '创建很容易!';
您还可以通过解析 HTML 文本来创建元素。所有子元素也会被解析和创建。
var elem2 = Element.html(
'<p>创建<em>很容易!</em></p>',
);
请注意,在前面的示例中, elem2
是一个 ParagraphElement
。
通过为元素分配父元素来将新创建的元素附加到文档。您可以将元素添加到任何现有元素的子元素中。在下面的示例中, body
是一个元素,它的子元素可以从 children
属性(作为 List<Element>
)访问。
document.body!.children.add(elem2);
添加、替换和删除节点
#回想一下,元素只是一种节点。您可以使用 Node 的 nodes
属性查找节点的所有子节点,该属性返回一个 List<Node>
(与省略非 Element 节点的 children
相反)。获得此列表后,您可以使用通常的 List 方法和运算符来操作节点的子节点。
要将节点作为其父节点的最后一个子节点添加,请使用 List 的 add()
方法:
querySelector('#inputs')!.nodes.add(elem);
要替换节点,请使用 Node 的 replaceWith()
方法:
querySelector('#status')!.replaceWith(elem);
要删除节点,请使用 Node 的 remove()
方法:
// 按 ID 查找节点,如果找到则将其从 DOM 中删除。
querySelector('#expendable')?.remove();
操作 CSS 样式
#CSS 或 级联样式表 定义了 DOM 元素的显示样式。您可以通过向元素附加 ID 和类属性来更改元素的外观。
每个元素都有一个 classes
字段,它是一个列表。只需向此集合添加和删除字符串即可添加和删除 CSS 类。例如,以下示例将 warning
类添加到元素:
var elem = querySelector('#message')!;
elem.classes.add('warning');
通过 ID 查找元素通常非常有效。您可以使用 id
属性动态设置元素 ID:
var message = DivElement();
message.id = 'message2';
message.text = '请订阅 Dart 邮件列表。';
您可以通过使用方法级联来减少此示例中的冗余文本:
var message = DivElement()
..id = 'message2'
..text = '请订阅 Dart 邮件列表。';
虽然使用 ID 和类将元素与一组样式关联是最佳实践,但有时您想直接将特定样式附加到元素:
message.style
..fontWeight = 'bold'
..fontSize = '3em';
处理事件
#要响应外部事件(例如点击、焦点更改和选择),请添加事件监听器。您可以向页面上的任何元素添加事件监听器。事件分派和传播是一个复杂的问题;如果您不熟悉 Web 编程,请 研究详细信息 。
使用 element.onEvent.listen(function)
添加事件处理程序,其中 Event
是事件名称,function
是事件处理程序。
例如,以下是如何处理按钮点击:
// 查找一个 ID 为 submitInfo 的按钮并添加一个事件处理程序。
querySelector('#submitInfo')!.onClick.listen((e) {
// 单击按钮时,它会运行此代码。
submitData();
});
事件可以在 DOM 树中向上和向下传播。要发现最初触发事件的元素,请使用 e.target
:
document.body!.onClick.listen((e) {
final clickedElem = e.target;
// ...
});
要查看您可以为其注册事件监听器的所有事件,请在 Element 及其子类的 API 文档中查找“onEventType”属性。一些常见的事件包括:
- change
- blur
- keyDown
- keyUp
- mouseDown
- mouseUp
使用 HttpRequest 使用 HTTP 资源
#您应该避免直接使用 dart:html
来发出 HTTP 请求。 dart:html
中的 HttpRequest
类是平台相关的,并且绑定到单个实现。 相反,请使用更高级别的库,例如 package:http
。
从互联网获取数据 教程解释了如何使用 package:http
发出 HTTP 请求。
使用 WebSockets 发送和接收实时数据
#WebSocket 允许您的 Web 应用与服务器交互式地交换数据——无需轮询。服务器创建 WebSocket 并侦听以 ws:// 开头的 URL 上的请求——例如,ws://127.0.0.1:1337/ws。通过 WebSocket 传输的数据可以是字符串或 blob。通常,数据是 JSON 格式的字符串。 要在您的 Web 应用中使用 WebSocket,首先创建一个 WebSocket 对象,并将 WebSocket URL 作为参数传递:
var ws = WebSocket('ws://echo.websocket.org');
发送数据
#要通过 WebSocket 发送字符串数据,请使用 send()
方法:
ws.send('Hello from Dart!');
接收数据
#要接收 WebSocket 上的数据,请为消息事件注册监听器:
ws.onMessage.listen((MessageEvent e) {
print('Received message: ${e.data}');
});
消息事件处理程序接收一个 MessageEvent 对象。此对象的 data
字段包含来自服务器的数据。
处理 WebSocket 事件
#您的应用可以处理以下 WebSocket 事件:open、close、error 和(如前所示)message。以下是如何创建一个 WebSocket 对象并为 open、close、error 和 message 事件注册处理程序的示例:
void initWebSocket([int retrySeconds = 1]) {
var reconnectScheduled = false;
print('连接到 websocket');
void scheduleReconnect() {
if (!reconnectScheduled) {
Timer(Duration(seconds: retrySeconds),
() => initWebSocket(retrySeconds * 2));
}
reconnectScheduled = true;
}
ws.onOpen.listen((e) {
print('已连接');
ws.send('Hello from Dart!');
});
ws.onClose.listen((e) {
print('Websocket 已关闭,将在 $retrySeconds 秒后重试');
scheduleReconnect();
});
ws.onError.listen((e) {
print('连接到 ws 时出错');
scheduleReconnect();
});
ws.onMessage.listen((MessageEvent e) {
print('收到消息:${e.data}');
});
}
更多信息
#本节只是粗略介绍了使用 dart:html
库。有关更多信息,请参阅 dart:html 的文档。Dart 还有其他库用于更专业的 Web API,例如 web 音频 、 IndexedDB 和 WebGL 。
有关 Dart Web 库的更多信息,请参阅 Web 库概述 。
除非另有说明,否则本网站上的文档反映的是 Dart 3.6.0。页面最后更新于 2025-02-05。 查看源代码 或 报告问题.