向 DOM 添加元素

What’s the point?

  • In Dart, page elements are of type Element.
  • An Element knows its parent.
  • An Element keeps its children in a List .
  • Change the DOM by adding or removing children of elements.
  • Respond to user input with an EventListener.

备忘: This page uses embedded DartPads to display runnable examples. If you see empty boxes instead of DartPads, go to theDartPad troubleshooting page.

如果你只看到了空白的框框(而没有任何内容),请查阅DartPad 常见问题页面

As you learned in the previous tutorial,the DOM represents the structureof a web page document using a simple tree structure.Each node in the tree represents an item on the page.Each node in the tree keeps track of bothits parent and its children.In Dart, theNodeclass contains the methods and propertiesthat implement a node’s tree functionality.

HTML page elements are one kind of node that can be in the DOM tree.They have a rectangular area on the page and can receive events.Examples of elements includeheading elements, paragraph elements, table elements,button elements, and so on.

In Dart,elements are implemented by theElementclass, which is a subclass of Node.Because the nodes you care about most are usually elements,this tutorial focuses on Element,rather than on Node.

Running the Todo app

In this tutorial, you will be working with a sample web appthat is a partial implementation of a todo list.This program dynamically changes the DOM,and therefore the web page,by adding elements to the DOM tree.

Try it!Click Run to start the web app.Then type in the app’s text field, and press return.The app adds an item to the list.Enter a few items into the input field.

This is the beginning of an app to manage a list of things to do.Right now, this app is for procrastinators onlybecause the program can only add items to your to do listbut not remove them.

About parent and child Elements in Dart

The Node class in Dart implements the basic treeing behaviorfor nodes in the Dart DOM.The Element class is a subclass of Node that implementsthe behavior specific to page element nodes.For example,an element knows the width and height ofits enclosing rectangle on the pageand it can receive events.

You can manipulate the DOM tree by adding and deleting nodes.However, many Dart apps are concerned only with page elements.So for convenience and code simplicity,the Element class implements APIfor interacting witha subset of the DOM that includesonly the nodes that are Elements.You can work with a virtual tree of Elementsrather than the more complex tree of Nodes.This tutorial shows you how to manipulate theDOM through the Element class.

An Element has a parent Elementand maintains references to its child Elements in a list.

An element with multiple child elements and a parent element

An Element has at most one parent Element.An Element’s parent is final and cannot be changed.So you cannot move an Element by changing its parent.Get an Element’s parent with the getter parent.For example, if you have an Element with the name anElementyou would refer to its parent element with anElement.parent.

Dart code reference to anElement's parent

An Element maintains references to its child elements in a list.Listis a class in the dart:core librarythat implements an indexable collection with a length.A list can be of fixed size or extendable.

List is an example of a generic (or parameterized) type—a typethat can declare formal type parameters.This means that a list can be declaredto contain only objects of a particular type.For example:

List declarationList description
List<String>list of strings
List<int>list of integers
List<Element>list of elements

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 operatorswhereby 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

You can change the tree structure by adding children toand removing children from an Element’s list of children.

Add a child element

When you change an Element or its child Elements in your Dart program,you change the DOM and therefore the web page.The browser re-renders the page automatically.

Setting up the page in HTML

Let’s take a look at the todo appto see how it dynamicallyadds an element to the DOMand displays a new item in the list of things to do.

The HTML code for the todo app sets up the initial HTML page,and thereby the initial DOM tree.You could get the same results using Dart code,but it’s usually better to define the primary page elementsin HTML code (easier to read, quicker to load).

todo app and its corresponding HTML code

The following diagram shows a partial DOM tree for the todo app.

The todo app and part of its DOM tree

Of interest are the two page elements that have IDs:to-do-input and to-do-list.The first identifies the <input> element into which the user types.The second identifies the <ul> (unordered list) elementcontaining the task items.Dart code adds elements to this listwhenever the user enters text into the input element.

Getting an element from the DOM

The following diagram showsthe Dart code for the todo app.

todo app and its corresponding Dart code

The main() function uses dart:html’s top-level querySelector()function to get the interesting elements from the DOM.Because calling querySelector() isn’t free,if a program refers to an element more than onceit should stash a reference to the element.

This program stashes a referenceto the input elementin a top-level variable called toDoInput.The unordered listis in the top-level variable toDoList.

Note the types of these variables: InputElement and UListElement.These are both subclasses of Element.The dart:html library has dozens of Element subclasses,many of which correspond to certain HTML tags.This program uses three:

HTML tagDart class
<input>InputElement
<ul>UListElement
<li>LIElement

Registering an event handler

When a user enters text into the input field,a change event fires,indicating that the value in the input field has just changed.The todo app defines a function, addToDoItem(),that can handle these change events.The following code connects addToDoItem() to the input field:

Add an event handler to the toDoInput element

Rather than dissect this busy line of code,think of it as a Dart idiomfor adding an event handler to an Element.

Dart idiom: Add an event handler to an Element

A change event is just one of many different types of eventsthat an input element can generate.For example, you can use click to handle mouse clicks,or keyDown for when the user presses a key on the keyboard.

About EventListener functions

The argument passed to the listen() method is a _callback function_of typeEventListener.EventListener is a typedef defined in the dart:html library as follows:

  1. typedef void EventListener(Event event)

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

  1. void addToDoItem(Event e) { ... }

The Event object passed into an EventListener functioncarries information about the Event that occurred.For example, the Event object knows which Element fired the event,and when.For location-specific events such as mouse clicks,the Event object also knows where the event occurred.

The addToDoItem() function ignores the Event object passed to it.

Adding an element to the DOM tree

The change event handler has the following code:

The addToDoItem() function explained

The final line of code is where the DOM gets changed.

An Element keeps references to all of its children in a list called children.By adding and removing elements to and from this list,the code changes the DOM.When the DOM changes, the browser re-renders the browser page.The effect, in our todo app, is that a new bullet item appearsin the to do list.

Styling the page elements

Let’s take a look at the CSS file for this app.

The effect of CSS styles

This code uses three different kinds of CSS selectors.The first is an HTML element selector that matches the <body> elementand sets some basic style attributes,such as the background color,for the entire page.Next in the file are two ID selectors:#to-do-input controls the appearance of the input fieldand #to-do-list sets the appearance of the unordered list elementin general.The elements in the list are controlled by the final rule,which uses both an ID selector and an HTML selector.This rule matches all <li> elements in theelement with the ID to-do-list, thus stylingeach item in the to do list.

Moving elements within the DOM tree

The Anagram app shows how to move an element within the DOM.

Try it!Click Run to start the web app.Then form a word by clicking the app’s letter tiles.You might prefer toopenthe app in DartPadto have more space for the app’s code and UI.

When the program starts,it creates one button element for each of sevenrandomly selected letters.The program adds each button to a DOM element—a simple<div> element identified by the CSS selector letterpile—witha call to letterpile.children.add().

Dart code populates the letter pile with buttons

Each button element in the letter pilehas a mouse click handler called moveLetter().If the button is in the letterpile,the mouse click handler moves the button to the end of the word.If the button is in the word,the mouse click handler moves the button back to the letter pile.

To move the button from the letter pile to the word or back,the code simply adds the button to a DOM elementthat is different from the button’s current parent.Because an element can have only one parent,adding the button to a different parentautomatically removes it from its previous parent.

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

The += operator is a compound assignment operator,which combines an operation (+) with an assignment.

The scrabbleValues variable is aMap—adata structure that contains key/value pairs.Use the square bracket syntax to retrieve a value by its keyand the length property to get the number of pairs it contains.

Other resources

  • You can find more information about the DOM and CSS in the language tour, which also provides thorough coverage of the Dart language.

What next?

The next tutorial, Remove DOM Elements,describes how to remove elements from the DOM and items off your todo list.