Contents

Add elements to the DOM

What’s the point?

  • 在Dart中,页面元素的类型为Element.
  • 元素知道其父级.
  • 元素将其子元素保留在列表<Element>中.
  • 通过添加或删除元素的子元素来更改DOM.
  • 使用EventListener响应用户输入.

正如您在上一教程中所学到的那样,DOM使用简单的树形结构表示网页文档的结构. 树中的每个节点代表页面上的一个项目. 树中的每个节点都跟踪其父代和子代. 在Dart中, Node类包含实现节点树功能的方法和属性.

HTML页面元素是可以在DOM树中的一种节点. 它们在页面上有一个矩形区域,可以接收事件. 元素的示例包括标题元素,段落元素,表格元素,按钮元素等.

在Dart中,元素是由Element类(它是Node的子类)实现的. 因为您最关心的节点通常是元素,所以本教程重点关注Element,而不是Node.

Running the Todo app

在本教程中,您将使用示例Web应用程序,该应用程序是待办事项列表的部分实现. 该程序通过向DOM树中添加元素来动态更改DOM,从而动态更改网页.

尝试一下! 单击运行以启动该Web应用程序. 然后在应用程序的文本字段中键入,然后按回车键. 该应用程序将一个项目添加到列表中. 在输入字段中输入一些项目.

这是应用程序管理要做的事情列表的开始. 目前,此应用仅适用于拖延症患者,因为该程序只能将项目添加到待办事项列表中,而不能将其删除.

About parent and child Elements in Dart

Dart中的Node类为Dart DOM中的节点实现了基本的树状行为. Element类是Node的子类,它实现特定于页面元素节点的行为. 例如,元素知道页面上其封闭矩形的宽度和高度,并且可以接收事件.

您可以通过添加和删除节点来操作DOM树. 但是,许多Dart应用程序仅与页面元素有关. 因此,为方便起见和简化代码,Element类实现了用于与DOM子集进行交互的API,该子集仅包含作为Elements的节点. 您可以使用虚拟的Elements树而不是更复杂的Node树. 本教程向您展示如何通过Element类操纵DOM.

元素具有父元素,并在列表中维护对其子元素的引用.

An element with multiple child elements and a parent element

一个元素最多具有一个父元素. 元素的父元素是最终的,不能更改. 因此,不能通过更改元素的父元素来移动它. 用getter parent获得Element的父元素. 例如,如果你有一个元素的名称anElement你指的是与它的父元素anElement.parent .

Dart code reference to anElement's parent

元素在列表中维护对其子元素的引用. List是dart:core库中的一个类,该类实现具有长度的可索引集合. 列表可以是固定大小或可扩展的.

List是通用 (或参数化 )类型的示例,该类型可以声明形式类型参数. 这意味着可以声明列表仅包含特定类型的对象. 例如:

清单声明 清单说明
List<String> 字符串列表
List<int> 整数列表
List<Element> 元素列表

An Element maintains references to its child element in a List<Element>, which your Dart code can refer to with the getter children. The List class has various methods and operators whereby you can refer to each child Element individually, iterate over the list, and add and remove elements.

Dart code references to anElement's list of children and individual child Elements

您可以通过将子级添加到Element的子级列表中并将子级删除来更改树结构.

Add a child element

当您在Dart程序中更改Element或其子Element时,将更改DOM并因此更改网页. 浏览器会自动重新呈现页面.

Setting up the page in HTML

让我们看一下todo应用程序,看看它如何动态地将元素添加到DOM并在要做的事情列表中显示一个新项.

todo应用程序的HTML代码设置了初始HTML页面,从而设置了初始DOM树. 使用Dart代码可以获得相同的结果,但是通常最好在HTML代码中定义主要页面元素(更易于阅读,加载更快).

todo app and its corresponding HTML code

下图显示了todo应用程序的部分DOM树.

The todo app and part of its DOM tree

感兴趣的是具有ID的两个页面元素: to-do-inputto-do-list . 第一个标识用户输入的<input>元素. 第二个标识包含任务项的<ul>(无序列表)元素. 每当用户在输入元素中输入文本时,Dart代码便会将元素添加到此列表中.

Getting an element from the DOM

下图显示了todo应用程序的Dart代码.

todo app and its corresponding Dart code

main()函数使用dart:html的顶级querySelector()函数从DOM中获取有趣的元素. 因为调用querySelector()并不是免费的,所以如果程序多次引用某个元素,则应存储对该元素的引用.

该程序在名为toDoInput的顶级变量中toDoInput对输入元素的引用. 无序列表位于顶级变量toDoList .

注意这些变量的类型:InputElement和UListElement. 这些都是Element的子类. dart:html库具有数十个Element子类,其中许多子类对应于某些HTML标签. 该程序使用三个:

HTML标签 飞镖类
<input> InputElement
<ul> UListElement
<li> LIElement

Registering an event handler

当用户在输入字段中输入文本时, 触发一个更改事件,指示输入字段中的值刚刚更改. 待办事项应用程序定义了一个函数addToDoItem(),可以处理这些更改事件. 以下代码将addToDoItem()连接到输入字段:

Add an event handler to the toDoInput element

与其剖析这段繁琐的代码行,不如将其视为向事件添加事件处理程序的Dart习惯用法.

Dart idiom: Add an event handler to an Element

更改事件只是输入元素可以生成的许多不同类型的事件之一. 例如,您可以使用click来处理鼠标单击,或者当用户按下键盘上的键时使用keyDown .

About EventListener functions

传递给listen()方法的参数是EventListener类型的回调函数 . EventListener是dart:html库中定义的typedef,如下所示:

typedef void EventListener(Event event)

As you can see, an EventListener returns no value (void) and takes an Event object as an argument. Any function with this signature is an EventListener. Based on its signature, the addToDoItem() function is an EventListener.

void addToDoItem(Event e) { ... }

传递到EventListener函数的Event对象携带有关发生的事件的信息. 例如,事件对象知道哪个元素触发了事件以及何时触发. 对于诸如鼠标单击之类的特定于位置的事件,Event对象还知道事件发生的位置.

addToDoItem()函数将忽略传递给它的Event对象.

Adding an element to the DOM tree

更改事件处理程序具有以下代码:

The addToDoItem() function explained

代码的最后一行是更改DOM的位置.

元素在称为children的列表中保留对其所有子级的引用. 通过在此列表中添加和删除元素,代码将更改DOM. DOM更改后,浏览器将重新渲染浏览器页面. 在我们的待办应用程序中,结果是新的项目符号出现在了待办事项列表中.

Styling the page elements

让我们看一下此应用程序的CSS文件.

The effect of CSS styles

这段代码使用了三种不同的CSS选择器. 第一个是与<body>元素匹配的HTML元素选择器,并为整个页面设置一些基本样式属性,例如背景色. 文件中的下一个是两个ID选择器:#to-do-input控制输入字段的外观,而#to-do-list通常设置无序列表元素的外观. 列表中的元素受最终规则控制,该规则同时使用ID选择器和HTML选择器. 此规则将元素中的所有<li>元素与ID待办事项列表进行匹配,从而对待办事项列表中的每个项目进行样式设置.

Moving elements within the DOM tree

Anagram应用程序显示了如何在DOM中移动元素.

尝试一下! 单击运行以启动该Web应用程序. 然后通过单击应用程序的字母拼贴来形成单词. 您可能希望在DartPad中打开该应用程序,以便为该应用程序的代码和UI提供更多空间.

程序启动时,它将为七个随机选择的字母中的每个字母创建一个按钮元素. 该程序将每个按钮添加到DOM元素(由CSS选择器letterpile标识的简单<div>元素),并调用letterpile.children.add().

Dart code populates the letter pile with buttons

字母堆中的每个按钮元素都有一个名为moveLetter()的鼠标单击处理程序. 如果按钮位于字母拼写中,则鼠标单击处理程序会将按钮移动到单词的末尾. 如果按钮在单词中,则鼠标单击处理程序会将按钮移回字母堆.

要将按钮从字母堆移动到单词或单词的后退,代码只需将按钮添加到与按钮当前父项不同的DOM元素中. 因为一个元素只能有一个父元素,所以将按钮添加到另一个父元素会自动将其从其前一个父元素中删除.

The mouse click handler adds the button to the word, thus moving it

+=运算符是复合赋值运算符,它将运算符( + )与赋值结合在一起.

scrabbleValues变量是一个Map —一种包含键/值对的数据结构. 使用方括号语法可通过其键检索值,并使用length属性可获取其包含的对数.

Other resources

  • 您可以在语言导览中找到有关DOM和CSS的更多信息,该指南也提供了有关Dart语言的全面介绍.

What next?

下一个教程" 删除DOM元素 "介绍了如何从DOM中删除元素以及待办事项列表中的项目.

by  ICOPY.SITE