连接 Dart 和 HTML

写一个迷你 Dart 应用

要点有哪些?
  • DartPad 让你不需要 HTML 引用编写一个简单的 Dart web 应用。
  • 一个 Dart 应用包括 Dart、HTML、和(通常)CSS 代码。
  • 编译 一个 web 应用的 Dart 代码为 JavaScript 来在任意现代浏览器中运行此应用。
  • HTML 文件管理浏览器页面中的 Dart 代码。
  • 树/节点的 DOM 结构,模拟浏览器页面。
  • 使用带 ID 的 querySelector() 来从 DOM 获取元素。
  • CSS 选择器用来选择匹配 DOM 中的元素。
  • 使用 CSS 规则来给元素添加样式。

要写一个 Dart web 应用,你需要明白几个概念——DOM 树、节点、元素、HTML,以及 Dart 语言和库。

这些概念是相互依赖的,但我们必须从某个地方开始,所以我们从一个简单的 HTML 文件开始,它介绍了 DOM 树和节点。从那里,你构建一个视图框架,从 Dart 应用剥离动态生成页面的代码。

虽然简单,但这个例子展示了如何连接 Dart 应用和 HTML 页面,以及一个 Dart 应用如何与页面上的元素相互作用。这些概念为更有趣、更有用的 web 应用提供了基础。

关于 Dart, HTML, 以及 CSS

如果你用过 DartPad,你已经看到了让你编写 web 应用代码的 DART、HTML 和 CSS 标签。这三个语言分别负责 web 应用的不同方面。

语言 用途
Dart 实现 web 应用的交互和动态行为
HTML 描述 web 应用页面的内容(文档和结构中的元素)
CSS 控制页面元素的外观

Dart 程序可以响应事件,例如鼠标点击,动态地操作 web 页面上的元素,以及保存信息。在 web 应用被部署之前,Dart 代码必须被编译为 JavaScript 代码。

HTML 是一种描述 web 页面的语言。它使用标签设置页面的初始结构,为页面添加元素,并为页面交互嵌入任意脚本。HTML 设置初始的文档树,并指定元素类型、CSS 类和 ID,这些允许 HTML、CSS 和 Dart 程序来引用相同的元素。

CSS 表示层叠样式表(Cascading Style Sheets),描述了文档中元素的外观。CSS 控制格式的许多方面,例如:字体、字号、颜色、背景色、边框、外边距,以及对齐。

关于 DOM

文档对象模型(DOM)表示作为节点树的 web 文档的结构。当一个 HTML 文件被浏览器加载,浏览器解析 HTML 并在一个窗口显示文档。下图展示了一个简单的 HTML 文件以及在 Chrome 浏览器中生成的 web 页面。

HTML 使用标签描述文档。例如,上图简单的 HTML 代码中使用<title>标签描述页面的标题,使用<h1>描述一级标题头,使用<p>描述段落。在 HTML 代码中的一些标签,比如<head><body>在 web 页面是不可见的,但对于文档结构是有用的。

在 DOM 中,document 对象作为 DOM 树的根(它没有父节点)。在 DOM 树中不同类型的节点代表文档中不同类型的对象。例如,DOM 树包含页面元素、文本节点、属性节点。下面是上图中简单的 HTML 文件的 DOM 树。

注意这些标签,比如<p>段落标签,它代表多个节点。段落本身是一个元素节点。段落中的文本是一个文本节点(有时候,可能是一个包含许多节点的子树)。ID 是一个属性节点。

除了根节点,每个节点在 DOM 树中只有一个父节点。每个节点可以有多个子节点。

HTML 文件定义了文档的初始结构。Dart 或 JavaScript 可以通过添加、删除动态地修改文档,并修改 DOM 树中的节点。当 DOM 发生改变,浏览器立刻重新渲染窗口。

上图展示了一小段 Dart 程序,它通过动态更改一个段落文本来相应地改变 DOM。程序可以添加和删除节点,甚至插入整个子节点树。

创建一个新的 Dart 应用

  1. 进入 DartPad
  2. 点击 New Pad 按钮,撤销你上次在 DartPad 做的所有更改。

注意:这些 DartPad 的功能隐藏了一些 HTML 引用代码。如果你想要使用任何其它的编辑器,我们推荐从一个小的 Dart web 应用示例开始,并修改<body>中没有<script>标签的部分。HTML and Dart connections 展示了完整的 HTML 代码。

编辑 HTML 源码

  1. 点击 DartPad 左上角的 HTML。从 Dart 代码视图,切换到(不存在的) HTML 代码视图。
  2. 添加下面的 HTML 代码。
<p id="RipVanWinkle">
  RipVanWinkle paragraph.
</p>
  1. 点击 HTML OUTPUT 查看浏览器如何渲染 HTML。

关于 HTML 源码

这段 HTML 代码和在本教程先前各种图里显示的 HTML 代码相似,但它更简单。在 DartPad 中,你真正需要关心的唯一的标签——本例中的<p>。你不需要关心包裹着它的标签,例如<html><body>。因为 DartPad 知道你的 Dart 代码在哪里,你不需要一个<script>标签。

注意HTML and Dart connections 展示了在 DartPad 之外运行 web 应用的全部 HTML 代码。

这个段落标签有一个“RipVanWinkle”标识符。你在下一步创建的 Dart 代码会使用这个 ID 来获取段落元素。

编辑 Dart 源码

  1. 点击 DartPad 左上角的 DART。从 HTML 代码视图切换到 Dart 代码视图。
  2. 按如下所示修改 Dart 代码。
import 'dart:html';

void main() {
  querySelector('#RipVanWinkle').text = 'Wake up, sleepy head!';
}
  1. 点击 Run 来执行代码。

在 HTML OUTPUT 标签页中的文本变为 “Wake up, sleepy head!”

关于 Dart 源码

让我们逐句查看这段 Dart 代码。

导入库

import指令导入了指定的库,使这个库里的所有类和函数在你的程序里可用。

import 'dart:html';

这段程序导入了 Dart 的 HTML 库,它包含了操作 DOM 的关键类和函数。关键的类有:

Dart 类 描述
Node 实现一个 DOM 节点。
Element 一个 Node 的子类;实现一个 web 页面元素。
Document Node 的另一个子类;实现文档对象。

Dart 核心库包含另外有用的类:List,一个可以指定它的成员类型的参数化的类。List<Element> 一个 Element 保存它的子 Element 的列表的实例。

使用 querySelector() 函数

应用的main()函数包含一行代码,它有点像多个事情接连发生的连写语句。让我们拆解它。

querySelector()是一个通过 Dart HTML 库提供的顶级函数,它从 DOM 获取元素对象。

querySelector('#RipVanWinkle').text = 'Wake up, sleepy head!';

querySelector()的参数——一个字符串,是一个用于标识该对象的 CSS 选择器。最常见的 CSS 选择器指定类、标识符、或属性。当我们之后向迷你应用中添加一个 CSS 文件时,会详细考虑这些选择器。在本例中,RipVanWinkle是 HTML 文件中声明的段落元素的唯一 ID,#RipVanWinkle指定了这个 ID。

querySelector('#RipVanWinkle').text = 'Wake up, sleepy head!';

从 DOM 获取元素的另一个有用的方法是querySelectorAll(),它返回匹配提供的选择器的所有元素对象的列表。

设置一个元素的文本

在 DOM 中,一个页面元素的文本包含一个子节点,具体而言,一个文本节点。在下图中,包含字符串 “RipVanWinkle paragraph.” 的节点是一个文本节点。

更复杂的文本,例如,带样式变化或嵌入链接和图片的文本,表现为一个文本节点和其它对象的子节点树。

在 Dart 中,你可以简单地使用元素地text属性,它有一个 getter 为你遍历本节点的子节点树,并提取它们的文本。

querySelector('#RipVanWinkle').text = 'Wake up, sleepy head!';

然而,如果这个文本节点有样式(因此,是一个子节点树),获取文本然后立刻设置它,可能会改变 DOM ,这是由于丢失了子节点树的信息。通常,和我们的 RipVanWinkle 例子一样,这种简化没有副作用。

赋值操作符(=)设置通过querySelector()函数返回的元素的文本为字符串“Wake up, sleepy head!”。

querySelector('#RipVanWinkle').text = 'Wake up, sleepy head!';

这导致浏览器立刻重新渲染包含这个应用的网页,从而在网页上动态地显示文本。

HTML 和 Dart 相关联

Dart web 应用在运行时动态地改变在浏览器窗口中的文本。当然,只给网页添加文本并不做其它事情可以直接由 HTML 完成。这个小应用仅仅向你展示了如何连接一个 Dart 应用和一个网页。

在 DartPad 中,Dart 代码和 HTML 代码之间唯一的关联是这个RipVanWinkleID。

要在 DartPad 之外运行你的应用,你需要编译 Dart 代码为 JavaScript。使用 build_runner build 命令编译你的应用为可部署的 JavaScript。然后,你需要关联 HTML 和生成的 JavaScript:你必须在 HTML 添加<script>标签来告诉浏览器在哪里找到编译的 Dart 代码。

下面是本应用完整的 HTML 代码,假设 Dart 代码是在名为main.dart的文件中:

<!DOCTYPE html>

<html>
  <head>
    <title>A Minimalist App</title>
    <script defer src="main.dart.js"></script>
  </head>
  <body>
    <p id="RipVanWinkle">
      RipVanWinkle paragraph.
    </p>
  </body>
</html>

使用 CSS 给应用添加样式

大多数 HTML 使用级联样式表(CSS)来定义样式控制页面元素的外观。让我们为这个迷你应用自定义 CSS。

  1. 点击CSS。从 Dart 代码视图切换到(不存在的) CSS 代码视图。
  2. 添加下面的 CSS 代码:
#RipVanWinkle {
  font-size: 20px;
  font-family: 'Open Sans', sans-serif;
  text-align: center;
  margin-top: 20px;
  background-color: SlateBlue;
  color: Yellow;
}

在 HTML OUTPUT 下面立刻显示变化来反映新的样式,这仅应用于 ID 是RipVanWinkle的页面元素。

关于 CSS 选择器

CSS 选择器可以是,关于在 HTML 中建立的元素的ID、CSS 类和其它信息。你的 Dart 代码可以使用这个信息通过一个 CSS 选择器来获取元素——一个用来从 DOM 中选择匹配元素的模式。CSS 选择器允许 CSS、HTML 和 Dart 代码来引用相同的对象。通常,一个选择器指定一个 ID、一个 HTML 元素类型、一个 CSS 类或一个属性。选择器也可以被嵌套。

CSS 选择器在 Dart 程序中是很重要的,因为你通过querySelector()querySelectorAll()使用它们从 DOM 中获取匹配的元素。很多时候,Dart 程序通过querySelector()使用 ID 选择器,通过querySelectorAll()使用类选择器。

下面是一些 CSS 选择器的例子:

选择器类型 例子 描述
ID 选择器 #RipVanWinkle 匹配一个单一的,唯一的元素
HTML 元素 p 匹配所有的段落
HTML 元素 h1 匹配所有的 h1 标题
CSS 类 .classname 匹配所有使用这个类名的条目
通配符 * 匹配所有元素
属性 input[type=”button”] 匹配所有 input 元素的按钮

如你所见,迷你应用使用了一个 CSS 选择器——ID 选择器#RipVanWinkle,即使当时还没有 CSS 文件。你不需要为一个 Dart 程序创建一个 CSS 文件。你也不需要因要使用一个 CSS 选择器而创建一个 CSS 文件。CSS 选择器是建立在 HTML 文件中,并通过 Dart 程序用来选择匹配的元素。

让我们看看迷你应用的 CSS 代码。迷你应用的 CSS 文件有一条 CSS 规则。一个 CSS 规则有两个主要部分:一个选择器和一组声明。

在迷你应用中,选择器#RipVanWinkle是一个 ID 选择器,通过哈希符号 (#)标识;它通过指定的 ID 匹配单独的、唯一的元素——我们现在要替换的RipVanWinkle paragraph元素。RipVanWinkle是 HTML 文件中的 ID。在 CSS 文件和 Dart 代码中使用哈希符号(#)引用它。在 HTML 文件中指定类名不需要句点(.),在 CSS 文件和 Dart 代码中使用一个句点(.)引用它。

在 CSS 规则的花括号之中的是一系列声明,每个都以分号(;)结尾。每个声明指定一个属性和它的值。这一组声明合起来为所有匹配的元素定义了样式表。样式表用来设置在网页上匹配元素的外观。

RipVanWinkle paragraph元素的 CSS 规则指定了几个属性;例如,它设置文本颜色为黄色。

其它资源

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,108评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,699评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,812评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,236评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,583评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,739评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,957评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,704评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,447评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,643评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,133评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,486评论 3 256
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,151评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,108评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,889评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,782评论 2 277
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,681评论 2 272

推荐阅读更多精彩内容