You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In the 20+ years since its standardization, JavaScript has come a very long way. While in 2020, JavaScript can be used on servers, in data science, and even on IoT devices, it is important to remember its most popular use case: web browsers.
Websites are made up of HTML and/or XML documents. These documents are static, they do not change. The *Document Object Model (DOM)* is a programming interface implemented by browsers to make static websites functional. The DOM API can be used to change the document structure, style, and content. The API is so powerful that countless frontend frameworks (jQuery, React, Angular, etc.) have been developed around it to make dynamic websites even easier to develop.
15
+
网站由 HTML 和/或 XML 文档组成。这些文档是静态的,不会改变。*文档对象模型(DOM)*是浏览器实现的一个编程接口,用于使静态网站变得可操作。DOM API 可用于更改文档结构、样式和内容。该 API 十分强大,强大到无数前端框架(jQuery、React 以及 Angular 等)都是围绕它开发的,其使得动态网站的开发变得更加容易。
16
16
17
-
TypeScript is a typed superset of JavaScript, and it ships type definitions for the DOM API. These definitions are readily available in any default TypeScript project. Of the 20,000+ lines of definitions in _lib.dom.d.ts_, one stands out among the rest: `HTMLElement`. This type is the backbone for DOM manipulation with TypeScript.
17
+
TypeScript 是 JavaScript 的一个类型超集,并且它提供了 DOM API 的类型定义。这些定义在任何默认的 TypeScript 项目中都可以使用。在 _lib.dom.d.ts_ 文件的两万多行定义中,有一个脱颖而出:`HTMLElement`。这个类型是使用 TypeScript 进行 DOM 操作的关键。
18
18
19
-
> You can explore the source code for the [DOM type definitions](https://github.com/microsoft/TypeScript/blob/main/src/lib/dom.generated.d.ts)
// 1. Select the div element using the id property
40
+
// 1. 使用 id 属性选择 div 元素
41
41
const app =document.getElementById("app");
42
42
43
-
// 2. Create a new <p></p> element programmatically
43
+
// 2.以编程方式创建一个新的 <p></p> 元素
44
44
const p =document.createElement("p");
45
45
46
-
// 3. Add the text content
46
+
// 3. 添加文本内容
47
47
p.textContent="Hello, World!";
48
48
49
-
// 4. Append the p element to the div element
49
+
// 4. 将 p 元素附加到 div 元素中
50
50
app?.appendChild(p);
51
51
```
52
52
53
-
After compiling and running the _index.html_page, the resulting HTML will be:
53
+
编译并运行 _index.html_页面后,生成的 HTML 将为:
54
54
55
55
```html
56
56
<divid="app">
57
57
<p>Hello, World!</p>
58
58
</div>
59
59
```
60
60
61
-
## The `Document`Interface
61
+
## `Document`接口
62
62
63
-
The first line of the TypeScript code uses a global variable `document`. Inspecting the variable shows it is defined by the `Document` interface from the _lib.dom.d.ts_file. The code snippet contains calls to two methods, `getElementById`and`createElement`.
Pass it an element id string and it will return either `HTMLElement`or`null`. This method introduces one of the most important types, `HTMLElement`. It serves as the base interface for every other element interface. For example, the `p`variable in the code example is of type `HTMLParagraphElement`. Also, take note that this method can return `null`. This is because the method can't be certain pre-runtime if it will be able to actually find the specified element or not. In the last line of the code snippet, the new _optional chaining_ operator is used to call `appendChild`.
73
+
向它传递一个元素 id 字符串,它将返回 `HTMLElement`或`null`。这个方法引入了最重要的类型之一:`HTMLElement`。它是每个其他元素接口的基础接口。例如,代码示例中的 `p`变量的类型为 `HTMLParagraphElement`。另外,请注意这个方法可能返回 `null`。这是因为该方法在运行时无法确定是否能找到指定的元素。在代码片段的最后一行,我们使用了新的*可选链接(optional chaining)*运算符来调用 `appendChild`。
74
74
75
75
### `Document.createElement`
76
76
77
-
The definition for this method is (I have omitted the _deprecated_ definition):
This is an overloaded function definition. The second overload is simplest and works a lot like the `getElementById`method does. Pass it any `string` and it will return a standard HTMLElement. This definition is what enables developers to create unique HTML element tags.
84
+
这是一个重载的函数定义。第二个重载是最简单的,与 `getElementById`方法的工作方式很相似。向它传递任何 `string`,它将返回标准的 HTMLElement。这个定义使开发者能够创建独特的 HTML 元素标签。
85
85
86
-
For example `document.createElement('xyz')`returns a `<xyz></xyz>`element, clearly not an element that is specified by the HTML specification.
86
+
例如,`document.createElement('xyz')`返回一个 `<xyz></xyz>`元素,显然这不是 HTML 规范中指定的元素。
87
87
88
-
> For those interested, you can interact with custom tag elements using the `document.getElementsByTagName`
For the first definition of `createElement`, it is using some advanced generic patterns. It is best understood broken down into chunks, starting with the generic expression: `<KextendskeyofHTMLElementTagNameMap>`. This expression defines a generic parameter `K` that is _constrained_ to the keys of the interface `HTMLElementTagNameMap`. The map interface contains every specified HTML tag name and its corresponding type interface. For example here are the first 5 mapped values:
Some elements do not exhibit unique properties and so they just return `HTMLElement`, but other types do have unique properties and methods so they return their specific interface (which will extend from or implement `HTMLElement`).
Now, for the remainder of the `createElement`definition: `(tagName: K, options?: ElementCreationOptions): HTMLElementTagNameMap[K]`. The first argument `tagName`is defined as the generic parameter `K`. The TypeScript interpreter is smart enough to _infer_ the generic parameter from this argument. This means that the developer does not have to specify the generic parameter when using the method; whatever value is passed to the `tagName`argument will be inferred as `K` and thus can be used throughout the remainder of the definition. This is exactly what happens; the return value `HTMLElementTagNameMap[K]`takes the `tagName`argument and uses it to return the corresponding type. This definition is how the `p`variable from the code snippet gets a type of `HTMLParagraphElement`. And if the code was `document.createElement('a')`, then it would be an element of type `HTMLAnchorElement`.
The `document.getElementById`function returns an `HTMLElement`. `HTMLElement`interface extends the`Element`interface which extends the `Node`interface. This prototypal extension allows for all `HTMLElements`to utilize a subset of standard methods. In the code snippet, we use a property defined on the `Node`interface to append the new `p`element to the website.
The last line of the code snippet is `app?.appendChild(p)`. The previous, `document.getElementById`, section detailed that the _optional chaining_ operator is used here because `app`can potentially be null at runtime. The `appendChild`method is defined by:
This method works similarly to the `createElement`method as the generic parameter `T`is inferred from the `newChild`argument. `T`is _constrained_ to another base interface `Node`.
Previously, this document details the `HTMLElement`interface extends from `Element`which extends from `Node`. In the DOM API there is a concept of _children_ elements. For example in the following HTML, the `p`tags are children of the `div`element
123
+
之前,本文详细介绍了 `HTMLElement`接口继承自 `Element`,而 `Element`又继承自 `Node`。在 DOM API 中,有一个称为*子级(children)*元素的概念。例如,在以下 HTML 中,`p`标签是 `div`元素的子级
124
124
125
125
```tsx
126
126
<div>
@@ -137,9 +137,9 @@ div.childNodes;
137
137
// NodeList(2) [p, p]
138
138
```
139
139
140
-
After capturing the `div`element, the `children`prop will return an `HTMLCollection` list containing the `HTMLParagraphElements`. The `childNodes`property will return a similar `NodeList`list of nodes. Each `p`tag will still be of type `HTMLParagraphElements`, but the `NodeList`can contain additional _HTML nodes_ that the `HTMLCollection`list cannot.
Modify the HTML by removing one of the `p`tags, but keep the text.
142
+
修改 HTML 代码,删除其中一个 `p`标签,但保留文本内容。
143
143
144
144
```tsx
145
145
<div>
@@ -156,48 +156,48 @@ div.childNodes;
156
156
// NodeList(2) [p, text]
157
157
```
158
158
159
-
See how both lists change. `children`now only contains the `<p>Hello, World</p>`element, and the `childNodes`contains a `text`node rather than two `p`nodes. The `text` part of the `NodeList`is the literal `Node` containing the text `TypeScript!`. The `children`list does not contain this `Node` because it is not considered an `HTMLElement`.
## The `querySelector`and`querySelectorAll`methods
161
+
## `querySelector`和`querySelectorAll`方法
162
162
163
-
Both of these methods are great tools for getting lists of dom elements that fit a more unique set of constraints. They are defined in _lib.dom.d.ts_as:
163
+
这两个方法都是很好的工具,可以获取符合更多独特约束条件的 DOM 元素列表。它们在 _lib.dom.d.ts_中定义如下:
164
164
165
165
```ts
166
166
/**
167
-
* Returns the first element that is a descendant of node that matches selectors.
The `querySelectorAll`definition is similar to `getElementsByTagName`, except it returns a new type: `NodeListOf`. This return type is essentially a custom implementation of the standard JavaScript list element. Arguably, replacing `NodeListOf<E>`with`E[]`would result in a very similar user experience. `NodeListOf`only implements the following properties and methods: `length`, `item(index)`, `forEach((value,key,parent) =>void)`, and numeric indexing. Additionally, this method returns a list of _elements_, not _nodes_, which is what `NodeList` was returning from the `.childNodes`method. While this may appear as a discrepancy, take note that interface `Element`extends from `Node`.
To see these methods in action modify the existing code to:
183
+
要查看这些方法的实际应用,我们可以修改现有的代码如下:
184
184
185
185
```tsx
186
186
<ul>
187
-
<li>First:)</li>
188
-
<li>Second!</li>
189
-
<li>Thirdtimesacharm.</li>
187
+
<li>第一个:)</li>
188
+
<li>第二个!</li>
189
+
<li>第三个也不错。</li>
190
190
</ul>;
191
191
192
-
constfirst = document.querySelector("li"); //returns the first li element
193
-
constall = document.querySelectorAll("li"); //returns the list of all li elements
192
+
constfirst = document.querySelector("li"); //返回第一个 li 元素
193
+
constall = document.querySelectorAll("li"); //返回所有 li 元素的列表
194
194
```
195
195
196
-
## Interested in learning more?
196
+
## 想了解更多?
197
197
198
-
The best part about the _lib.dom.d.ts_ type definitions is that they are reflective of the types annotated in the Mozilla Developer Network (MDN) documentation site. For example, the `HTMLElement`interface is documented by this [HTMLElement page](https://developer.mozilla.org/docs/Web/API/HTMLElement) on MDN. These pages list all available properties, methods, and sometimes even examples. Another great aspect of the pages is that they provide links to the corresponding standard documents. Here is the link to the [W3C Recommendation for HTMLElement](https://www.w3.org/TR/html52/dom.html#htmlelement).
0 commit comments