Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
回答:**1 和 3**。

所有命令行都是将 `text` “作为文本”添加到 `elem`。
这两个命令都会将 `text` “作为文本”添加到 `elem`

这里有个简单的例子
这是一个例子

```html run height=80
<div id="elem1"></div>
Expand All @@ -12,7 +12,7 @@
let text = '<b>text</b>';

elem1.append(document.createTextNode(text));
elem2.textContent = text;
elem3.innerHTML = text;
elem2.innerHTML = text;
elem3.textContent = text;
</script>
```
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ importance: 5

---

# 对比 createTextNodeinnerHTML textContent
# createTextNode vs innerHTML vs textContent

我们有一个空的 DOM 元素 `elem` 和一个字符串 `text`。

以下这三个命令行的结果是一样的吗
下面这 3 个命令中的哪个命令做的是完全相同的事儿

1. `elem.append(document.createTextNode(text))`
2. `elem.innerHTML = text`
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
首先,使用 HTML/CSS。
首先,让我们编写 HTML/CSS。

每个时间组件在`<span>`标签中看起来很棒
时间的每个组件都有其自己的 `<span>`,那将会看起来很棒

```html
<div id="clock">
<span class="hour">hh</span>:<span class="min">mm</span>:<span class="sec">ss</span>
</div>
```

我们还会用 CSS 丰富样式
另外,我们需要使用 CSS 为它们着色

`update` 会刷新时钟,它调用 `setInterval` 每秒刷新一次
函数 `update` 会刷新时钟, `setInterval` 每秒调用一次

```js
function update() {
Expand All @@ -32,14 +32,14 @@ function update() {
}
```

在这行 `(*)` 我们每秒检查当前时间。调用 `setInterval` 并不是完全可靠:它有可能发生延迟现象
`(*)` 行中,我们每次都检查当前时间。`setInterval` 调用并不可靠:它们可能会发生延迟现象

时钟管理函数:

```js
let timerId;

function clockStart() { // run the clock
function clockStart() { // 运行时钟
timerId = setInterval(update, 1000);
update(); // (*)
}
Expand All @@ -50,4 +50,4 @@ function clockStop() {
}
```

请留意 `update()`,它不单在 `clockStart()` 被间隔器调用,也会在 `(*)` 立即调用一次。如果不是这样,只有在 `setInterval` 第一次执行周期时,才能看到时钟,在此之前时钟一直都是空的
请注意,`update()` 不仅在 `clockStart()` 中被调度,而且还立即在 `(*)` 行运行。否则,访问者将不得不等到 `setInterval` 第一次执行。在那之前,时钟将是空的
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ importance: 4

---

# setInterval 的彩色时钟
# 使用 setInterval 的彩色时钟

创建一个彩色时钟
创建一个像这样的彩色时钟

[iframe src="solution" height=60]

使用 HTML/CSS 进行样式设计,JavaScript 仅仅用来更新元素中的时间
使用 HTML/CSS 进行样式设计,JavaScript 仅用来更新元素中的时间
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

当我们需要在 HTML 某处插入元素,`insertAdjacentHTML` 是最好方案
具体做法
当我们需要在某处插入 HTML ,`insertAdjacentHTML` 是最适合的方案

解决方法

```js
one.insertAdjacentHTML('afterend', '<li>2</li><li>3</li>');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ importance: 5

---

# 将 HTML 标签中插入列表
# 将 HTML 插入到列表中

编写需要插入的文本代码 `<li>2</li><li>3</li>`,插入到两个 `<li>` 之中
编写代码,将 `<li>2</li><li>3</li>`,插入到两个 `<li>` 之间

```html
<ul id="ul">
Expand Down
23 changes: 11 additions & 12 deletions 2-ui/1-document/07-modifying-document/12-sort-table/solution.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
这个方法很精简,但是看起来有点难理解,所以我添加了一些注释:

这个解决方案虽然很短,但可能看起来有点难理解,因此,在这里我提供了一些扩展性的注释:

```js
let sortedRows = Array.from(table.rows)
.slice(1)
.sort((rowA, rowB) => rowA.cells[0].innerHTML > rowB.cells[0].innerHTML ? 1 : -1);
let sortedRows = Array.from(table.tBodies[0].rows) // 1
.sort((rowA, rowB) => rowA.cells[0].innerHTML.localeCompare(rowB.cells[0].innerHTML));

table.tBodies[0].append(...sortedRows);
table.tBodies[0].append(...sortedRows); // (3)
```

1. 使用 `table.querySelectorAll('tr')` 获取所有 `<tr>`,然后生成数组,因为我们需要用到数组方法。
2. 第一个 TR(`table.rows[0]`)实际上是 table 头,所以我们需要调用 `.slice(1)` 裁剪掉。
3. 比较 `<td>` 的内容(字符在字符集中的序号),进行排序。
4. 现在使用 `.append(...sortedRows)` 插入节点。
对此算法一步一步进行讲解:

1. 从 `<tbody>` 获取所有 `<tr>`。
2. 然后将它们按第一个 `<td>`(`name` 字段)中的内容进行比较。
3. 然后使用 `.append(...sortedRows)` 按正确的顺序插入节点。

table 永远包含 <tbody> 元素,所以我们需要考虑到它,并将内容插入到其中:单纯的调用 `table.append(...)` 将会失败
我们不必删除行元素,只需要“重新插入”,它们就会自动离开原来的位置

请留意:我们没有移除操作,只进行“重复插入”,它们会将旧的位置的内容自动去除
P.S. 在我们的例子中,表格中有一个明确的 `<tbody>`,但即使 HTML 中的表格没有 `<tbody>`,DOM 结构也总是具有它
54 changes: 25 additions & 29 deletions 2-ui/1-document/07-modifying-document/12-sort-table/task.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,34 @@ importance: 5

---

# Sort the table
# 对表格进行排序

There's a table:
下面是一个表格:

```html run
<table>
<tr>
<th>Name</th>
<th>Surname</th>
<th>Age</th>
</tr>
<tr>
<td>John</td>
<td>Smith</td>
<td>10</td>
</tr>
<tr>
<td>Pete</td>
<td>Brown</td>
<td>15</td>
</tr>
<tr>
<td>Ann</td>
<td>Lee</td>
<td>5</td>
</tr>
<tr>
<td>...</td>
<td>...</td>
<td>...</td>
</tr>
<thead>
<tr>
<th>Name</th><th>Surname</th><th>Age</th>
</tr>
</thead>
<tbody>
<tr>
<td>John</td><td>Smith</td><td>10</td>
</tr>
<tr>
<td>Pete</td><td>Brown</td><td>15</td>
</tr>
<tr>
<td>Ann</td><td>Lee</td><td>5</td>
</tr>
<tr>
<td>...</td><td>...</td><td>...</td>
</tr>
</tbody>
</table>
```

可能会有更多的行数
可能会有更多行

编写代码对 `"name"` 列进行排序
编写代码,按 `"name"` 列对其进行排序
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

首先我们看看**错误**的做法:
首先,让我们看看 **错误** 的做法:

```js
function clear(elem) {
Expand All @@ -9,7 +9,7 @@ function clear(elem) {
}
```

这是无效的,因为调用 `remove()` 从前面开始移除 `elem.childNodes` 集合里元素,元素的起始下标一直都是 `0`但是 `i` 却一直在增长,有的元素会直接被忽略了
这是行不通的,因为调用 `remove()` 会从首端开始移除 `elem.childNodes` 集合中的元素,因此,元素每次都从索引 `0` 开始。但是 `i` 在增加,所以元素就被跳过了

用 `for..of` 循环的结果也跟上面一样。

Expand All @@ -23,7 +23,7 @@ function clear(elem) {
}
```

这里还有一种更简便的方法,也能达到我们需要的效果
还有一种更简单的方法,也可以达到我们所要的效果

```js
function clear(elem) {
Expand Down
10 changes: 5 additions & 5 deletions 2-ui/1-document/07-modifying-document/5-why-aaa/solution.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
HTML 在这个任务中是错误的,这也是造成怪异的原因所在
这个题目中的 HTML 是错的。这就是造成怪异现象的原因

浏览器会自动修复它。但 `<table>` 可能会没有文本:根据 table 的特殊规范,这是允许的。所以浏览器会在 `<table>` **前面**添加 `"aaa"`
浏览器必须自动修复它。但 `<table>` 内可能会没有文本:根据规范,只允许特定于表格的标签。所以浏览器把 `"aaa"` 添加到了 `<table>` **前面**。

现在当我们移除 table 时,它就被保留下来了
当我们删除表格后,文本 `"aaa"` 仍然存在的原因就很明显了吧

通过浏览器开发者工具很容易就能在 DOM 找到答案。它显示出 `"aaa"` 在 `<table>` 前面。
通过使用浏览器开发者工具查看 DOM,就可以轻松地回答这个问题。从浏览器开发者工具中我们可以看到,`"aaa"` 在 `<table>` 前面。

HTML 标准规范详细描述了对于异常的 HTML 会如何处理,以及浏览器的行为是否合乎规范
HTML 标准规范详细描述了如何处理错误的 HTML,并且浏览器的这种行为是正确的
10 changes: 7 additions & 3 deletions 2-ui/1-document/07-modifying-document/5-why-aaa/task.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ importance: 1

# 为什么留下 "aaa"?

运行下面例子,为什么 `table.remove()` 没有删除 `"aaa"` 文本?
在下面这个示例中,我们调用 `table.remove()` 从文档中删除表格。

但如果运行它,你就会看到文本 `"aaa"` 并没有被删除。

这是为什么?

```html height=100 run
<table id="table">
Expand All @@ -15,9 +19,9 @@ importance: 1
</table>

<script>
alert(table); // table 应该显示出的样子
alert(table); // 表格,就是它应有的样子

table.remove();
// 为什么 aaa 依旧在文档中
// 为什么 aaa 还存在于文档中?
</script>
```
Original file line number Diff line number Diff line change
@@ -1 +1 @@
请留意 `textContent` 复制 `<li>` 内容的用法
请注意使用 `textContent` `<li>` 的内容进行赋值的用法
12 changes: 6 additions & 6 deletions 2-ui/1-document/07-modifying-document/6-create-list/task.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ importance: 4

# 创建一个列表

编写一个接口,根据用户输入生成一个列表
编写一个接口,根据用户输入创建一个列表(list)

每一个列表项
对于每个列表项

1. 使用 `prompt` 询问用户输入的内容
2. 创建 `<li>` 并添加到 `<ul>`。
3. 重复以上两步,直到用户输入取消指令(按下 `key:Esc` 或者 prompt CANCEL)。
1. 使用 `prompt` 向用户询问列表项的内容
2. 使用用户输入的内容创建 `<li>`并添加到 `<ul>`。
3. 重复以上步骤,直到用户取消输入(按下 `key:Esc` 键,或点击 `prompt` 弹窗的 CANCEL 按钮)。

所有元素应该都是动态创建的。

如果把用户输入了 HTML 标签,就应该将其视为文本
如果用户输入了 HTML 标签,那么这些内容应该被视为文本进行后续处理

[demo src="solution"]
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
在对象间游走的最简单方式就是递归了
遍历对象的最简单的方法是使用递归

1. [The solution with innerHTML](sandbox:innerhtml).
2. [The solution with DOM](sandbox:build-tree-dom).
1. [使用 innerHTML 的解决方案](sandbox:innerhtml)
2. [使用 DOM 的解决方案](sandbox:build-tree-dom)
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ importance: 5

---

# 利用对象创建节点树
# 从对象创建树

编写一个函数 `createTree` 将嵌套的对象生成 `ul/li` 的嵌套列表
编写一个函数 `createTree`,从嵌套对象创建一个嵌套的 `ul/li` 列表(list)

例如:

Expand All @@ -28,24 +28,24 @@ let data = {
};
```

语句
语法

```js
let container = document.getElementById('container');
*!*
createTree(container, data); // container 中创建树。
createTree(container, data); // 将树创建在 container
*/!*
```

结果(树)看起来像这样:

[iframe border=1 src="build-tree-dom"]

选择其中一种方式来完成这个任务
选择下面两种方式中的一种,来完成这个任务

1. 通过树创建 HTML 然后派发给 `container.innerHTML`。
2. 创建节点树然后插入到 DOM
1. 为树创建 HTML,然后将它们赋值给 `container.innerHTML`。
2. 创建节点树,并使用 DOM 方法将它们附加(append)上去

如果两种方式都尝试一下就更好
如果这两种方式你都做,那就太好了

P.S. 树应该没有“额外”的元素,像空的 `<ul></ul>` 没有列表项
P.S. 树上不应该有“多余”的元素,例如空的 `<ul></ul>` 叶子节点
Original file line number Diff line number Diff line change
@@ -1 +1 @@
为每个 `<li>` 插入文本,我们可以改变文本节点 `data`。
为了将文本附加到每个 `<li>` 中,我们可以改变文本节点的 `data`。
4 changes: 2 additions & 2 deletions 2-ui/1-document/07-modifying-document/8-tree-count/task.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ importance: 5

这里有一棵由嵌套的 `ul/li` 组成的树。

编写代码在 `<li>` 添加后代数量的数字。跳过一些叶子(如果节点没有后代节点)。
编写代码,为每个 `<li>` 添加其后代数量。跳过叶子节点(没有子代的节点)。

最终结果
结果

[iframe border=1 src="solution"]
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
我们用字符串创建 table:`"<table>...</table>"`,然后派发给 `innerHTML`。
我们将表格创建为字符串:`"<table>...</table>"`,然后将其赋值给 `innerHTML`。

算法如下:

1. 通过 `<th>` 创建 table 头和周末名字
1. 创建一个日期对象 `d = new Date(year, month-1)`。它是`月份`的第一天(注意 JavaScript 计算月份是从 `0` 开始,而不是 `1`)。
2. 将每月第一天的日期生成单元格,直到月份的第一天 `d.getDay()` 是空的。然后将它们填充到 `<td></td>`。
3. 天数增长 `d`:`d.setDate(d.getDate()+1)`。如果 `d.getMonth()` 不是下一个月,就添加新单元格 `<td>` 到日历表中,如果那天是星期日,就添加一行 <code>"&lt;/tr&gt;&lt;tr&gt;"</code>。
4. 如果天数遍历完但 table 没有填满,就用空的 `<td>` 补齐。
1. 使用 `<th>` 创建带有星期名的表头
2. 创建日期对象 `d = new Date(year, month-1)`。它是 `month` 的第一天(考虑到 JavaScript 中的月份从 `0` 开始,而不是从 `1` 开始)。
3. 直到月份的第一天 `d.getDay()`,前面的几个单元格是空的。让我们用 `<td></td>` 填充它们
4. 天数增长 `d`:`d.setDate(d.getDate()+1)`。如果 `d.getMonth()` 还没到下一个月,那么就将新的单元格 `<td>` 添加到日历中。如果那天是星期日,就添加一个新行 <code>"&lt;/tr&gt;&lt;tr&gt;"</code>。
5. 如果该月结束,但表格的行尚未填满,就用空的 `<td>` 补齐。
Loading