chore(i8n,learn): processed translations (#41061)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
This commit is contained in:
committed by
GitHub
parent
05a97d19fb
commit
785405fdfd
@ -19,10 +19,11 @@ dashedName: define-the-head-and-body-of-an-html-document
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<!-- metadata elements -->
|
<meta />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<!-- page contents -->
|
<div>
|
||||||
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
```
|
```
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: 5a8b073d06fa14fcfde687aa
|
id: 5a8b073d06fa14fcfde687aa
|
||||||
title: Exercise Tracker
|
title: Exercise 追踪器
|
||||||
challengeType: 4
|
challengeType: 4
|
||||||
forumTopicId: 301505
|
forumTopicId: 301505
|
||||||
dashedName: exercise-tracker
|
dashedName: exercise-tracker
|
||||||
@ -8,17 +8,17 @@ dashedName: exercise-tracker
|
|||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|
||||||
Build a full stack JavaScript app that is functionally similar to this: <https://exercise-tracker.freecodecamp.rocks/>. Working on this project will involve you writing your code using one of the following methods:
|
构建一个 JavaScript 的全栈应用,在功能上与这个应用相似: <https://exercise-tracker.freecodecamp.rocks/>。 可以采用下面的一种方式完成这个挑战:
|
||||||
|
|
||||||
- Clone [this GitHub repo](https://github.com/freeCodeCamp/boilerplate-project-exercisetracker/) and complete your project locally.
|
- 克隆 [this GitHub repo](https://github.com/freeCodeCamp/boilerplate-project-exercisetracker/) 并在本地完成项目。
|
||||||
- Use [our repl.it starter project](https://repl.it/github/freeCodeCamp/boilerplate-project-exercisetracker) to complete your project.
|
- 使用 [repl.it 初始化项目](https://repl.it/github/freeCodeCamp/boilerplate-project-exercisetracker) 来完成项目。
|
||||||
- Use a site builder of your choice to complete the project. Be sure to incorporate all the files from our GitHub repo.
|
- 使用你选择的网站生成器来完成项目, 并确保包含了我们 GitHub 仓库的所有文件。
|
||||||
|
|
||||||
When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the `Solution Link` field. Optionally, also submit a link to your project's source code in the `GitHub Link` field.
|
当完成本项目,请确认有一个正常运行的 demo 可以公开访问。 然后将 URL 提交到 `Solution Link` 中。 此外,还可以将项目的源码提交到 `GitHub Link` 中。
|
||||||
|
|
||||||
# --hints--
|
# --hints--
|
||||||
|
|
||||||
You should provide your own project, not the example URL.
|
提交自己的项目,而不是示例的 URL。
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) => {
|
(getUserInput) => {
|
||||||
@ -29,7 +29,7 @@ You should provide your own project, not the example URL.
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
You can `POST` to `/api/exercise/new-user` with form data `username` to create a new user. The returned response will be an object with `username` and `_id` properties.
|
可以将表单里的 `username` 通过 `POST` 请求发送到 `/api/exercise/new-user`,以创建一个新的用户。 返回的响应内容是一个带有 `username` 和 `_id` 的对象
|
||||||
|
|
||||||
```js
|
```js
|
||||||
async (getUserInput) => {
|
async (getUserInput) => {
|
||||||
@ -49,7 +49,7 @@ async (getUserInput) => {
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
You can make a `GET` request to `api/exercise/users` to get an array of all users. Each element in the array is an object containing a user's `username` and `_id`.
|
可以发送 `GET` 请求到 `api/exercise/users`,以获取一个所有用户的数组, 数组里的每个元素都是一个包含 `username` 和 `_id` 的用户对象。
|
||||||
|
|
||||||
```js
|
```js
|
||||||
async (getUserInput) => {
|
async (getUserInput) => {
|
||||||
@ -66,7 +66,7 @@ async (getUserInput) => {
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
You can `POST` to `/api/exercise/add` with form data `userId=_id`, `description`, `duration`, and optionally `date`. If no date is supplied, the current date will be used. The response returned will be the user object with the exercise fields added.
|
你能用表单里的 `userId=_id`,`description`,`duration` 和 `date`(可选)发送 `POST` 请求到 `/api/exercise/add`。 如果没有传入 date,默认采用当前日期。 响应内容是包含 exercise 表单内容的 user 对象。
|
||||||
|
|
||||||
```js
|
```js
|
||||||
async (getUserInput) => {
|
async (getUserInput) => {
|
||||||
@ -102,7 +102,7 @@ async (getUserInput) => {
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
You can make a `GET` request to `/api/exercise/log` with a parameter of `userId=_id` to retrieve a full exercise log of any user. The returned response will be the user object with a `log` array of all the exercises added. Each log item has the `description`, `duration`, and `date` properties.
|
可以向 `/api/exercise/log` 发送参数为 `userId=_id` 的 `GET` 请求,并检索全部的 exercise 日志。 响应内容是一个 user 对象,它带有一个 `log` 属性,该属性的值是所有被添加的 exercises 表单记录组成的数组, 每一个 log 数组里的元素应该是一个含有 `description`、`duration` 和 `date` 等属性的对象。
|
||||||
|
|
||||||
```js
|
```js
|
||||||
async (getUserInput) => {
|
async (getUserInput) => {
|
||||||
@ -144,7 +144,7 @@ async (getUserInput) => {
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
A request to a user's log (`/api/exercise/log`) returns an object with a `count` property representing the number of exercises returned.
|
用户日志请求 (`/api/exercise/log`) 返回一个带有 `count` 属性的对象,该属性反映 exercises 表单的成功提交次数(译者注:即 log 属性元素的个数)。
|
||||||
|
|
||||||
```js
|
```js
|
||||||
async (getUserInput) => {
|
async (getUserInput) => {
|
||||||
@ -185,7 +185,7 @@ async (getUserInput) => {
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
You can add `from`, `to` and `limit` parameters to a `/api/exercise/log` request to retrieve part of the log of any user. `from` and `to` are dates in `yyyy-mm-dd` format. `limit` is an integer of how many logs to send back.
|
可以把 `from`、`to` 和 `limit` 等参数添加到 `/api/exercise/log` 的请求,以查询该用户的部分 exercise 表单提交记录, `from` 和 `to` 是 `yyyy-mm-dd` 形式的日期, `limit` 是希望返回的 log 数量。
|
||||||
|
|
||||||
```js
|
```js
|
||||||
async (getUserInput) => {
|
async (getUserInput) => {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: bd7158d8c443edefaeb5bd0f
|
id: bd7158d8c443edefaeb5bd0f
|
||||||
title: File Metadata Microservice
|
title: 文件元数据微服务
|
||||||
challengeType: 4
|
challengeType: 4
|
||||||
forumTopicId: 301506
|
forumTopicId: 301506
|
||||||
dashedName: file-metadata-microservice
|
dashedName: file-metadata-microservice
|
||||||
@ -8,21 +8,21 @@ dashedName: file-metadata-microservice
|
|||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|
||||||
Build a full stack JavaScript app that is functionally similar to this: <https://file-metadata-microservice.freecodecamp.rocks/>. Working on this project will involve you writing your code using one of the following methods:
|
构建一个 JavaScript 的全栈应用,在功能上与这个应用相似:<https://file-metadata-microservice.freecodecamp.rocks/>。 可以采用下面的一种方式完成这个挑战:
|
||||||
|
|
||||||
- Clone [this GitHub repo](https://github.com/freeCodeCamp/boilerplate-project-filemetadata/) and complete your project locally.
|
- 克隆 [this GitHub repo](https://github.com/freeCodeCamp/boilerplate-project-filemetadata/) 并在本地完成项目。
|
||||||
- Use [our repl.it starter project](https://repl.it/github/freeCodeCamp/boilerplate-project-filemetadata) to complete your project.
|
- 使用 [repl.it 初始化项目](https://repl.it/github/freeCodeCamp/boilerplate-project-filemetadata) 来完成项目。
|
||||||
- Use a site builder of your choice to complete the project. Be sure to incorporate all the files from our GitHub repo.
|
- 使用你选择的网站生成器来完成项目, 并确保包含了我们 GitHub 仓库的所有文件。
|
||||||
|
|
||||||
When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the `Solution Link` field. Optionally, also submit a link to your projects source code in the `GitHub Link` field.
|
当完成本项目,请确认有一个正常运行的 demo 可以公开访问。 然后将 URL 提交到 `Solution Link` 中。 此外,还可以将项目的源码提交到 `GitHub Link` 中。
|
||||||
|
|
||||||
# --instructions--
|
# --instructions--
|
||||||
|
|
||||||
**HINT:** You can use the `multer` npm package to handle file uploading.
|
** 提示:** 可以使用 `multer` npm 包来处理上传文件
|
||||||
|
|
||||||
# --hints--
|
# --hints--
|
||||||
|
|
||||||
You should provide your own project, not the example URL.
|
提交自己的项目,而不是示例的 URL。
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) => {
|
(getUserInput) => {
|
||||||
@ -34,7 +34,7 @@ You should provide your own project, not the example URL.
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
You can submit a form that includes a file upload.
|
可以提交一个包含上传文件的表单。
|
||||||
|
|
||||||
```js
|
```js
|
||||||
async (getUserInput) => {
|
async (getUserInput) => {
|
||||||
@ -45,7 +45,7 @@ async (getUserInput) => {
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
The form file input field has the `name` attribute set to `upfile`.
|
表单的文件上传标签的 `name` 属性设置成 `upfile`。
|
||||||
|
|
||||||
```js
|
```js
|
||||||
async (getUserInput) => {
|
async (getUserInput) => {
|
||||||
@ -56,7 +56,7 @@ async (getUserInput) => {
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
When you submit a file, you receive the file `name`, `type`, and `size` in bytes within the JSON response.
|
当提交一个文件时,在 JSON 响应中收到文件的 `name`、`type` 和`size`(以 bytes(字节)为单位)。
|
||||||
|
|
||||||
```js
|
```js
|
||||||
async (getUserInput) => {
|
async (getUserInput) => {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: bd7158d8c443edefaeb5bdff
|
id: bd7158d8c443edefaeb5bdff
|
||||||
title: Request Header Parser Microservice
|
title: 请求头解析器微服务
|
||||||
challengeType: 4
|
challengeType: 4
|
||||||
forumTopicId: 301507
|
forumTopicId: 301507
|
||||||
dashedName: request-header-parser-microservice
|
dashedName: request-header-parser-microservice
|
||||||
@ -8,17 +8,17 @@ dashedName: request-header-parser-microservice
|
|||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|
||||||
Build a full stack JavaScript app that is functionally similar to this: <https://request-header-parser-microservice.freecodecamp.rocks/>. Working on this project will involve you writing your code using one of the following methods:
|
构建一个 JavaScript 的全栈应用,在功能上与这个应用相似:<https://request-header-parser-microservice.freecodecamp.rocks/>。 可以采用下面的一种方式完成这个挑战:
|
||||||
|
|
||||||
- Clone [this GitHub repo](https://github.com/freeCodeCamp/boilerplate-project-headerparser/) and complete your project locally.
|
- 克隆 [this GitHub repo](https://github.com/freeCodeCamp/boilerplate-project-headerparser/) 并在本地完成项目。
|
||||||
- Use [our repl.it starter project](https://repl.it/github/freeCodeCamp/boilerplate-project-headerparser) to complete your project.
|
- 使用 [repl.it 初始化项目](https://repl.it/github/freeCodeCamp/boilerplate-project-headerparser) 来完成项目。
|
||||||
- Use a site builder of your choice to complete the project. Be sure to incorporate all the files from our GitHub repo.
|
- 使用你选择的网站生成器来完成项目, 并确保包含了我们 GitHub 仓库的所有文件。
|
||||||
|
|
||||||
When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the `Solution Link` field. Optionally, also submit a link to your project's source code in the `GitHub Link` field.
|
当完成本项目,请确认有一个正常运行的 demo 可以公开访问。 然后将 URL 提交到 `Solution Link` 中。 此外,还可以将项目的源码提交到 `GitHub Link` 中。
|
||||||
|
|
||||||
# --hints--
|
# --hints--
|
||||||
|
|
||||||
You should provide your own project, not the example URL.
|
提交自己的项目,而不是示例的 URL。
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) => {
|
(getUserInput) => {
|
||||||
@ -30,7 +30,7 @@ You should provide your own project, not the example URL.
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
A request to `/api/whoami` should return a JSON object with your IP address in the `ipaddress` key.
|
向 `/api/whoami` 发送请求,返回一个 JSON 对象,这个JSON 对象应该含有存放 IP 地址的 `ipaddress` 键中。
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) =>
|
(getUserInput) =>
|
||||||
@ -42,7 +42,7 @@ A request to `/api/whoami` should return a JSON object with your IP address in t
|
|||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
A request to `/api/whoami` should return a JSON object with your preferred language in the `language` key.
|
向 `/api/whoami` 发送请求,返回一个 JSON 对象,这个 JSON 对象应该含有存放语言首选项的 `language` 键。
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) =>
|
(getUserInput) =>
|
||||||
@ -54,7 +54,7 @@ A request to `/api/whoami` should return a JSON object with your preferred langu
|
|||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
A request to `/api/whoami` should return a JSON object with your software in the `software` key.
|
向 `/api/whoami` 发送请求,返回一个 JSON 对象,这个 JSON 对象应该含有存放(发送请求的)软件的 `software` 键。
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) =>
|
(getUserInput) =>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: bd7158d8c443edefaeb5bdef
|
id: bd7158d8c443edefaeb5bdef
|
||||||
title: Timestamp Microservice
|
title: 时间戳微服务
|
||||||
challengeType: 4
|
challengeType: 4
|
||||||
forumTopicId: 301508
|
forumTopicId: 301508
|
||||||
dashedName: timestamp-microservice
|
dashedName: timestamp-microservice
|
||||||
@ -8,17 +8,17 @@ dashedName: timestamp-microservice
|
|||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|
||||||
Build a full stack JavaScript app that is functionally similar to this: <https://timestamp-microservice.freecodecamp.rocks/>. Working on this project will involve you writing your code using one of the following methods:
|
构建一个 JavaScript 的全栈应用,在功能上与这个应用相似:<https://timestamp-microservice.freecodecamp.rocks/>。 可以采用下面的任意一种方式完成这个挑战:
|
||||||
|
|
||||||
- Clone [this GitHub repo](https://github.com/freeCodeCamp/boilerplate-project-timestamp/) and complete your project locally.
|
- 克隆 [this GitHub repo](https://github.com/freeCodeCamp/boilerplate-project-timestamp/) 并在本地完成项目。
|
||||||
- Use [our repl.it starter project](https://repl.it/github/freeCodeCamp/boilerplate-project-timestamp) to complete your project.
|
- 使用 [repl.it 初始化项目](https://repl.it/github/freeCodeCamp/boilerplate-project-timestamp) 来完成项目。
|
||||||
- Use a site builder of your choice to complete the project. Be sure to incorporate all the files from our GitHub repo.
|
- 使用你选择的网站生成器来完成项目, 并确保包含了我们 GitHub 仓库的所有文件。
|
||||||
|
|
||||||
When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the `Solution Link` field. Optionally, also submit a link to your projects source code in the `GitHub Link` field.
|
当完成本项目,请确认有一个正常运行的 demo 可以公开访问。 然后将 URL 提交到 `Solution Link` 中。 此外,还可以将项目的源码提交到 `GitHub Link` 中。
|
||||||
|
|
||||||
# --hints--
|
# --hints--
|
||||||
|
|
||||||
You should provide your own project, not the example URL.
|
提交自己的项目,而不是示例的 URL。
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) => {
|
(getUserInput) => {
|
||||||
@ -28,7 +28,7 @@ You should provide your own project, not the example URL.
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
A request to `/api/timestamp/:date?` with a valid date should return a JSON object with a `unix` key that is a Unix timestamp of the input date in milliseconds
|
向 `/api/timestamp/:date?` 发送一个带有有效日期的请求,应该很快(在几毫秒内)返回一个 JSON 对象,在这个 JSON 对象内有一个包含输入日期的 Unix 时间戳的 `unix` 键。
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) =>
|
(getUserInput) =>
|
||||||
@ -46,7 +46,7 @@ A request to `/api/timestamp/:date?` with a valid date should return a JSON obje
|
|||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
A request to `/api/timestamp/:date?` with a valid date should return a JSON object with a `utc` key that is a string of the input date in the format: `Thu, 01 Jan 1970 00:00:00 GMT`
|
向 `/api/timestamp/:date?` 发送一个带有有效日期的请求,应该返回一个 JSON 对象,在这个 JSON 对象内有一个包含如 `Thu, 01 Jan 1970 00:00:00 GMT` 格式的输入日期的 `utc` 键。
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) =>
|
(getUserInput) =>
|
||||||
@ -64,7 +64,7 @@ A request to `/api/timestamp/:date?` with a valid date should return a JSON obje
|
|||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
A request to `/api/timestamp/1451001600000` should return `{ unix: 1451001600000, utc: "Fri, 25 Dec 2015 00:00:00 GMT" }`
|
向 `/api/timestamp/1451001600000` 发送请求,应该返回 `{ unix: 1451001600000, utc: "Fri, 25 Dec 2015 00:00:00 GMT" }`。
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) =>
|
(getUserInput) =>
|
||||||
@ -81,7 +81,7 @@ A request to `/api/timestamp/1451001600000` should return `{ unix: 1451001600000
|
|||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
Your project can handle dates that can be successfully parsed by `new Date(date_string)`
|
程序能成功处理能被 `new Date(date_string)` 解析的日期。
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) =>
|
(getUserInput) =>
|
||||||
@ -98,7 +98,7 @@ Your project can handle dates that can be successfully parsed by `new Date(date_
|
|||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
If the input date string is invalid, the api returns an object having the structure `{ error : "Invalid Date" }`
|
如果传入的日期是无效的,将返回一个带有结构体 `{ error : "Invalid Date" }` 的对象。
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) =>
|
(getUserInput) =>
|
||||||
@ -112,7 +112,7 @@ If the input date string is invalid, the api returns an object having the struct
|
|||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
An empty date parameter should return the current time in a JSON object with a `unix` key
|
如果传入的参数是空日期,将返回一个包含当前时间的 `unix` 键的 JSON 对象。
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) =>
|
(getUserInput) =>
|
||||||
@ -127,7 +127,7 @@ An empty date parameter should return the current time in a JSON object with a `
|
|||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
An empty date parameter should return the current time in a JSON object with a `utc` key
|
如果传入的参数是空日期,将返回一个包含当前时间的 `utc` 键的 JSON 对象。
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) =>
|
(getUserInput) =>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: bd7158d8c443edefaeb5bd0e
|
id: bd7158d8c443edefaeb5bd0e
|
||||||
title: URL Shortener Microservice
|
title: 短网址微服务
|
||||||
challengeType: 4
|
challengeType: 4
|
||||||
forumTopicId: 301509
|
forumTopicId: 301509
|
||||||
dashedName: url-shortener-microservice
|
dashedName: url-shortener-microservice
|
||||||
@ -8,21 +8,21 @@ dashedName: url-shortener-microservice
|
|||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|
||||||
Build a full stack JavaScript app that is functionally similar to this: <https://url-shortener-microservice.freecodecamp.rocks/>. Working on this project will involve you writing your code using one of the following methods:
|
构建一个 JavaScript 的全栈应用,在功能上与这个应用相似:<https://url-shortener-microservice.freecodecamp.rocks/>。 可以采用下面的任意一种方式完成这个挑战:
|
||||||
|
|
||||||
- Clone [this GitHub repo](https://github.com/freeCodeCamp/boilerplate-project-urlshortener/) and complete your project locally.
|
- 克隆 [this GitHub repo](https://github.com/freeCodeCamp/boilerplate-project-filemetadata/) 并在本地完成项目。
|
||||||
- Use [our repl.it starter project](https://repl.it/github/freeCodeCamp/boilerplate-project-urlshortener) to complete your project.
|
- 使用 [repl.it 初始化项目](https://repl.it/github/freeCodeCamp/boilerplate-project-urlshortener) 来完成项目。
|
||||||
- Use a site builder of your choice to complete the project. Be sure to incorporate all the files from our GitHub repo.
|
- 使用你选择的网站生成器来完成项目, 并确保包含了我们 GitHub 仓库的所有文件。
|
||||||
|
|
||||||
When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the `Solution Link` field. Optionally, also submit a link to your projects source code in the `GitHub Link` field.
|
当完成本项目,请确认有一个正常运行的 demo 可以公开访问。 然后将 URL 提交到 `Solution Link` 中。 此外,还可以将项目的源码提交到 `GitHub Link` 中。
|
||||||
|
|
||||||
# --instructions--
|
# --instructions--
|
||||||
|
|
||||||
**HINT:** Do not forget to use a body parsing middleware to handle the POST requests. Also, you can use the function `dns.lookup(host, cb)` from the `dns` core module to verify a submitted URL.
|
**提示:** 请使用 body parsing 中间件来处理 POST 请求, 也可以使用 `dns` 核心模块中的 `dns.lookup(host, cb)` 函数验证提交的 URL。
|
||||||
|
|
||||||
# --hints--
|
# --hints--
|
||||||
|
|
||||||
You should provide your own project, not the example URL.
|
提交自己的项目,而不是示例的 URL。
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) => {
|
(getUserInput) => {
|
||||||
@ -34,7 +34,7 @@ You should provide your own project, not the example URL.
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
You can POST a URL to `/api/shorturl/new` and get a JSON response with `original_url` and `short_url` properties. Here's an example: `{ original_url : 'https://freeCodeCamp.org', short_url : 1}`
|
可以通过 POST 请求给 `/api/shorturl/new` 发送一个 URL,并返回一个带有 `original_url` 和 `short_url` 属性的 JSON 响应, 例如:`{ original_url : 'https://freeCodeCamp.org', short_url : 1}`。
|
||||||
|
|
||||||
```js
|
```js
|
||||||
async (getUserInput) => {
|
async (getUserInput) => {
|
||||||
@ -60,7 +60,7 @@ async (getUserInput) => {
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
When you visit `/api/shorturl/<short_url>`, you will be redirected to the original URL.
|
当访问 `/api/shorturl/<short_url>` 时, 将重定向到原来的 URL。
|
||||||
|
|
||||||
```js
|
```js
|
||||||
async (getUserInput) => {
|
async (getUserInput) => {
|
||||||
@ -94,7 +94,7 @@ async (getUserInput) => {
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
If you pass an invalid URL that doesn't follow the valid `http://www.example.com` format, the JSON response will contain `{ error: 'invalid url' }`
|
如果传入一个没有遵循如 `http://www.example.com` 的无效 URL,则返回包含 `{ error: 'invalid url' }` 的 JSON 响应。
|
||||||
|
|
||||||
```js
|
```js
|
||||||
async (getUserInput) => {
|
async (getUserInput) => {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: 587d7fb1367417b2b2512bf4
|
id: 587d7fb1367417b2b2512bf4
|
||||||
title: Chain Middleware to Create a Time Server
|
title: 通过链式调用中间件来创建时间服务
|
||||||
challengeType: 2
|
challengeType: 2
|
||||||
forumTopicId: 301510
|
forumTopicId: 301510
|
||||||
dashedName: chain-middleware-to-create-a-time-server
|
dashedName: chain-middleware-to-create-a-time-server
|
||||||
@ -8,9 +8,9 @@ dashedName: chain-middleware-to-create-a-time-server
|
|||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|
||||||
Middleware can be mounted at a specific route using `app.METHOD(path, middlewareFunction)`. Middleware can also be chained inside route definition.
|
使用 `app.METHOD(path, middlewareFunction)` 可以在指定的路由挂载中间件, 也可以在路由定义中链式调用中间件。
|
||||||
|
|
||||||
Look at the following example:
|
请看以下示例:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
app.get('/user', function(req, res, next) {
|
app.get('/user', function(req, res, next) {
|
||||||
@ -21,17 +21,17 @@ app.get('/user', function(req, res, next) {
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
This approach is useful to split the server operations into smaller units. That leads to a better app structure, and the possibility to reuse code in different places. This approach can also be used to perform some validation on the data. At each point of the middleware stack you can block the execution of the current chain and pass control to functions specifically designed to handle errors. Or you can pass control to the next matching route, to handle special cases. We will see how in the advanced Express section.
|
此方法可用于将服务操作拆分为较小的单元, 这可以让应用拥有更好的结构,也便于在不同的位置上复用代码; 此方法还可用于对数据执行某些验证。 可以在每一个中间件堆栈中,阻止当前链的执行,并将控制权传递给专门设计用于处理错误的函数; 或者可以将控制权传递给下一个匹配的路由,以处理特殊情况, 我们将在高级 Express 章节中看到这些内容。
|
||||||
|
|
||||||
# --instructions--
|
# --instructions--
|
||||||
|
|
||||||
In the route `app.get('/now', ...)` chain a middleware function and the final handler. In the middleware function you should add the current time to the request object in the `req.time` key. You can use `new Date().toString()`. In the handler, respond with a JSON object, taking the structure `{time: req.time}`.
|
在路由 `app.get('/now', ...)` 中链式调用中间件函数,并在最后处理。 在中间件函数中给请求对象中的 `req.time` 添加到当前时间, 可以使用 `new Date().toString()`, 在处理函数中,使用 `{time: req.time}` 结构的 JSON 对象来响应请求。
|
||||||
|
|
||||||
**Note:** The test will not pass if you don’t chain the middleware. If you mount the function somewhere else, the test will fail, even if the output result is correct.
|
**注意:** 如果不链式调用中间件,测试将不能通过。 如果将中间件函数挂载在其他地方,即使输出结果正确,测试也会失败。
|
||||||
|
|
||||||
# --hints--
|
# --hints--
|
||||||
|
|
||||||
The /now endpoint should have mounted middleware
|
/now 接口应该已经挂载了中间件
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) =>
|
(getUserInput) =>
|
||||||
@ -49,7 +49,7 @@ The /now endpoint should have mounted middleware
|
|||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
The /now endpoint should return a time that is +/- 20 secs from now
|
/now 接口应该返回一个现在时间 +/-20 秒的时间
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) =>
|
(getUserInput) =>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: 587d7fb2367417b2b2512bf8
|
id: 587d7fb2367417b2b2512bf8
|
||||||
title: Get Data from POST Requests
|
title: 从 POST 请求中获取数据
|
||||||
challengeType: 2
|
challengeType: 2
|
||||||
forumTopicId: 301511
|
forumTopicId: 301511
|
||||||
dashedName: get-data-from-post-requests
|
dashedName: get-data-from-post-requests
|
||||||
@ -8,27 +8,27 @@ dashedName: get-data-from-post-requests
|
|||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|
||||||
Mount a POST handler at the path `/name`. It’s the same path as before. We have prepared a form in the html frontpage. It will submit the same data of exercise 10 (Query string). If the body-parser is configured correctly, you should find the parameters in the object `req.body`. Have a look at the usual library example:
|
在路径 `/name` 挂载一个 POST 处理方法, 和前面一样, 我们已经在 html 首页准备了一份表格, 它将提交与练习 10 相同的数据(查询字符串), 如果 body-parser 正确配置好了,那么就可以在 `req.body` 对象中找到请求的参数。 来看看一个常规的例子:
|
||||||
|
|
||||||
<blockquote>route: POST '/library'<br>urlencoded_body: userId=546&bookId=6754 <br>req.body: {userId: '546', bookId: '6754'}</blockquote>
|
<blockquote>路由:POST '/library'<br>URL 编码的请求正文:userId=546&bookId=6754<br>req.body:{userId: '546', bookId: '6754'}</blockquote>
|
||||||
|
|
||||||
Respond with the same JSON object as before: `{name: 'firstname lastname'}`. Test if your endpoint works using the html form we provided in the app frontpage.
|
响应和前面一样的 JSON 对象 `{name: 'firstname lastname'}`。 你可以使用首页应用提供的 html 表单,来测试你的 API 是否正常工作。
|
||||||
|
|
||||||
Tip: There are several other http methods other than GET and POST. And by convention there is a correspondence between the http verb, and the operation you are going to execute on the server. The conventional mapping is:
|
提示:除了 GET 和 POST,还有其他几种 http 方法。 按照惯例,http 动词和在服务端执行的某种操作之间有对应关系, 这种对应关系通常如下:
|
||||||
|
|
||||||
POST (sometimes PUT) - Create a new resource using the information sent with the request,
|
POST(有时候是 PUT)- 使用请求发送信息,以创建新资源;
|
||||||
|
|
||||||
GET - Read an existing resource without modifying it,
|
GET- 读取不用修改的已存在的资源;
|
||||||
|
|
||||||
PUT or PATCH (sometimes POST) - Update a resource using the data sent,
|
PUT 或者 PATCH(有时候是 POST)- 发送数据,以更新资源;
|
||||||
|
|
||||||
DELETE => Delete a resource.
|
DELETE=> 删除一个资源。
|
||||||
|
|
||||||
There are also a couple of other methods which are used to negotiate a connection with the server. Except from GET, all the other methods listed above can have a payload (i.e. the data into the request body). The body-parser middleware works with these methods as well.
|
还有其他两种方法常用于与服务进行交互。 除了 GET 之外,上面列出的所有方法都可以负载数据(即数据都能放到消息正文中), 这些方法也可以使用 body-parser 中间件。
|
||||||
|
|
||||||
# --hints--
|
# --hints--
|
||||||
|
|
||||||
Test 1 : Your API endpoint should respond with the correct name
|
测试 1:你的 API 接口应该使用正确的名字来响应
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) =>
|
(getUserInput) =>
|
||||||
@ -46,7 +46,7 @@ Test 1 : Your API endpoint should respond with the correct name
|
|||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
Test 2 : Your API endpoint should respond with the correct name
|
测试 2:你的 API 接口应该使用正确的名字来响应
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) =>
|
(getUserInput) =>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: 587d7fb2367417b2b2512bf6
|
id: 587d7fb2367417b2b2512bf6
|
||||||
title: Get Query Parameter Input from the Client
|
title: 从客户端获取输入的查询参数
|
||||||
challengeType: 2
|
challengeType: 2
|
||||||
forumTopicId: 301512
|
forumTopicId: 301512
|
||||||
dashedName: get-query-parameter-input-from-the-client
|
dashedName: get-query-parameter-input-from-the-client
|
||||||
@ -8,19 +8,19 @@ dashedName: get-query-parameter-input-from-the-client
|
|||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|
||||||
Another common way to get input from the client is by encoding the data after the route path, using a query string. The query string is delimited by a question mark (?), and includes field=value couples. Each couple is separated by an ampersand (&). Express can parse the data from the query string, and populate the object `req.query`. Some characters, like the percent (%), cannot be in URLs and have to be encoded in a different format before you can send them. If you use the API from JavaScript, you can use specific methods to encode/decode these characters.
|
从客户端获取输入的另一种常见方式是使用查询字符串对路由路径中的数据进行编码, 查询字符串使用标记(?)分隔,并且包含键值对 field=value, 每对键值使用连字号(&)分隔。 Express 能够从查询字符串中解析这些数据,并且把它放到 `req.query` 对象中。 有些字符(如百分号(%))不能在出现在 URL 中,它们在发送前必须以不同的格式进行编码。 如果使用 JavaScript 的 API,可以用特定的方法来编码/解码这些字符。
|
||||||
|
|
||||||
<blockquote>route_path: '/library'<br>actual_request_URL: '/library?userId=546&bookId=6754' <br>req.query: {userId: '546', bookId: '6754'}</blockquote>
|
<blockquote>路由地址:'/library'<br> 实际请求 URL:'/library?userId=546&bookId=6754'<br>req.query:{userId: '546', bookId: '6754'}</blockquote>
|
||||||
|
|
||||||
# --instructions--
|
# --instructions--
|
||||||
|
|
||||||
Build an API endpoint, mounted at `GET /name`. Respond with a JSON document, taking the structure `{ name: 'firstname lastname'}`. The first and last name parameters should be encoded in a query string e.g. `?first=firstname&last=lastname`.
|
构建一个 API 接口,使用路由挂载在 `GET /name` 上, 使用一个 JSON 文件来响应,它的结构是这样的:`{ name: 'firstname lastname'}`, 名字(first name)和姓氏(last name)参数应该编码在查询参数中,例如:`?first=firstname&last=lastname`。
|
||||||
|
|
||||||
**Note:** In the following exercise you are going to receive data from a POST request, at the same `/name` route path. If you want, you can use the method `app.route(path).get(handler).post(handler)`. This syntax allows you to chain different verb handlers on the same path route. You can save a bit of typing, and have cleaner code.
|
**注意:** 在后面的练习中,我们将向相同的路由路径 `/name` 发送 POST 请求来接收数据。 如果愿意,可以使用`app.route(path).get(handler).post(handler)`这中写法, 这种语法允许在同一路径路由上链式调用不同的请求方法, 可以节省一点打字时间,也可以让代码看起来更清晰。
|
||||||
|
|
||||||
# --hints--
|
# --hints--
|
||||||
|
|
||||||
Test 1 : Your API endpoint should respond with the correct name
|
测试 1:你的 API 应该用正确的名字来响应
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) =>
|
(getUserInput) =>
|
||||||
@ -38,7 +38,7 @@ Test 1 : Your API endpoint should respond with the correct name
|
|||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
Test 2 : Your API endpoint should respond with the correct name
|
测试 2:你的 API 应该用正确的名字来响应
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) =>
|
(getUserInput) =>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: 587d7fb2367417b2b2512bf5
|
id: 587d7fb2367417b2b2512bf5
|
||||||
title: Get Route Parameter Input from the Client
|
title: 从客户端获取输入的路由参数
|
||||||
challengeType: 2
|
challengeType: 2
|
||||||
forumTopicId: 301513
|
forumTopicId: 301513
|
||||||
dashedName: get-route-parameter-input-from-the-client
|
dashedName: get-route-parameter-input-from-the-client
|
||||||
@ -8,17 +8,17 @@ dashedName: get-route-parameter-input-from-the-client
|
|||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|
||||||
When building an API, we have to allow users to communicate to us what they want to get from our service. For example, if the client is requesting information about a user stored in the database, they need a way to let us know which user they're interested in. One possible way to achieve this result is by using route parameters. Route parameters are named segments of the URL, delimited by slashes (/). Each segment captures the value of the part of the URL which matches its position. The captured values can be found in the `req.params` object.
|
在构建 API 时,要让用户告诉我们他们想从服务中获取什么。 举个例子,如果客户请求数据库中存储的用户信息,他们需要一种方法让我们知道他们对哪个用户感兴趣, 使用路由参数可以实现这个需求。 路由参数是由斜杠(/)分隔的 URL 命名段, 每一小段能捕获与其位置匹配的 URL 部分的值, 捕获的值能够在 `req.params` 对象中找到。
|
||||||
|
|
||||||
<blockquote>route_path: '/user/:userId/book/:bookId'<br>actual_request_URL: '/user/546/book/6754' <br>req.params: {userId: '546', bookId: '6754'}</blockquote>
|
<blockquote>路由地址:'/user/:userId/book/:bookId'<br> 实际请求 URL:'/user/546/book/6754'<br> req.params:{userId: '546', bookId: '6754'}</blockquote>
|
||||||
|
|
||||||
# --instructions--
|
# --instructions--
|
||||||
|
|
||||||
Build an echo server, mounted at the route `GET /:word/echo`. Respond with a JSON object, taking the structure `{echo: word}`. You can find the word to be repeated at `req.params.word`. You can test your route from your browser's address bar, visiting some matching routes, e.g. `your-app-rootpath/freecodecamp/echo`.
|
在路由 `GET /:word/echo` 中构建一个响应服务, 响应一个采用 `{echo: word}` 结构的 JSON 对象。 可以在 `req.params.word` 中找到要重复的单词, 可以在浏览器的地址栏测试你的路由,访问一些匹配的路由,比如:`your-app-rootpath/freecodecamp/echo`。
|
||||||
|
|
||||||
# --hints--
|
# --hints--
|
||||||
|
|
||||||
Test 1 : Your echo server should repeat words correctly
|
测试 1:你的 echo 服务应该正确地重复单词
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) =>
|
(getUserInput) =>
|
||||||
@ -36,7 +36,7 @@ Test 1 : Your echo server should repeat words correctly
|
|||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
Test 2 : Your echo server should repeat words correctly
|
测试 2:你的 echo 服务应该正确地重复单词
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) =>
|
(getUserInput) =>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: 587d7fb1367417b2b2512bf3
|
id: 587d7fb1367417b2b2512bf3
|
||||||
title: Implement a Root-Level Request Logger Middleware
|
title: 实现一个根级的请求记录中间件
|
||||||
challengeType: 2
|
challengeType: 2
|
||||||
forumTopicId: 301514
|
forumTopicId: 301514
|
||||||
dashedName: implement-a-root-level-request-logger-middleware
|
dashedName: implement-a-root-level-request-logger-middleware
|
||||||
@ -8,9 +8,9 @@ dashedName: implement-a-root-level-request-logger-middleware
|
|||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|
||||||
Earlier, you were introduced to the `express.static()` middleware function. Now it’s time to see what middleware is, in more detail. Middleware functions are functions that take 3 arguments: the request object, the response object, and the next function in the application’s request-response cycle. These functions execute some code that can have side effects on the app, and usually add information to the request or response objects. They can also end the cycle by sending a response when some condition is met. If they don’t send the response when they are done, they start the execution of the next function in the stack. This triggers calling the 3rd argument, `next()`.
|
前面我们介绍了 `express.static()` 中间件函数, 现在是时候更详细地了解什么是中间件了。 中间件函数是一个接收 3 个参数的函数,这 3 个参数分别是:请求对象、响应对象和在应用的请求-响应循环中的下一个函数。 中间件函数执行一些可能对应用程序产生一些效果的代码,通常还会在请求对象或者响应对象里添加一些信息, 它们也可以在满足某些条件时通过发送响应来结束循环, 如果在它们完成时没有发送响应,那么就会开始执行堆栈中的下一个函数, `next()` 将触发调用第 3 个参数。
|
||||||
|
|
||||||
Look at the following example:
|
看看下面的例子:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
function(req, res, next) {
|
function(req, res, next) {
|
||||||
@ -19,17 +19,17 @@ function(req, res, next) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Let’s suppose you mounted this function on a route. When a request matches the route, it displays the string “I’m a middleware…”, then it executes the next function in the stack. In this exercise, you are going to build root-level middleware. As you have seen in challenge 4, to mount a middleware function at root level, you can use the `app.use(<mware-function>)` method. In this case, the function will be executed for all the requests, but you can also set more specific conditions. For example, if you want a function to be executed only for POST requests, you could use `app.post(<mware-function>)`. Analogous methods exist for all the HTTP verbs (GET, DELETE, PUT, …).
|
假设在某个路由上安装了这个中间件函数, 当一个请求与路由匹配时,它会显示字符串“I’m a middleware…”,然后它执行堆栈中的下一个函数。 在这个练习中,我们将构建根级中间件。 正如我们在挑战 4 中看到的,要在根层级安装中间件函数,我们可以使用 `app.use(<mware-function>)` 方法。 在这种情况下,该函数将对所有请求执行,但也可以设置更具体的条件来执行, 例如,如果你希望某个函数只针对 POST 请求执行,可以使用 `app.post(<mware-function>)` 方法。 所有的 HTTP 动词(GET、DELETE、PUT……)都存在类似的方法。
|
||||||
|
|
||||||
# --instructions--
|
# --instructions--
|
||||||
|
|
||||||
Build a simple logger. For every request, it should log to the console a string taking the following format: `method path - ip`. An example would look like this: `GET /json - ::ffff:127.0.0.1`. Note that there is a space between `method` and `path` and that the dash separating `path` and `ip` is surrounded by a space on both sides. You can get the request method (http verb), the relative route path, and the caller’s ip from the request object using `req.method`, `req.path` and `req.ip`. Remember to call `next()` when you are done, or your server will be stuck forever. Be sure to have the ‘Logs’ opened, and see what happens when some request arrives.
|
构建一个简单的日志记录器。 对于每个请求,它应该在控制台中打印一个采用以下格式的字符串:`method path - ip`, 例如:`GET /json - ::ffff:127.0.0.1`。 注意 `method` 和 `path` 之间有一个空格,并且 `path` 和 `ip` 中间的破折号的两边都有空格。 可以使用 `req.method`、`req.path` 和 `req.ip` 从请求对象中分别获取请求方法(http 动词)、路由相对路径和请求者的 ip 信息。 当你完成时,记得要调用 `next()`,否则服务器将一直处于挂起状态。 请确保“Logs”是打开的,观察一下当一些请求到达时会发生什么事情。
|
||||||
|
|
||||||
**Note:** Express evaluates functions in the order they appear in the code. This is true for middleware too. If you want it to work for all the routes, it should be mounted before them.
|
**注意:**Express 按照函数在代码中出现的顺序来执行, 中间件也是如此。 如果你想让中间件函数适用于所有路由,那么应该在路由之前配置好中间件。
|
||||||
|
|
||||||
# --hints--
|
# --hints--
|
||||||
|
|
||||||
Root level logger middleware should be active
|
应该激活根级记录器中间件
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) =>
|
(getUserInput) =>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: 587d7fb0367417b2b2512bef
|
id: 587d7fb0367417b2b2512bef
|
||||||
title: Serve an HTML File
|
title: 提供 HTML 文件服务
|
||||||
challengeType: 2
|
challengeType: 2
|
||||||
forumTopicId: 301516
|
forumTopicId: 301516
|
||||||
dashedName: serve-an-html-file
|
dashedName: serve-an-html-file
|
||||||
@ -8,7 +8,7 @@ dashedName: serve-an-html-file
|
|||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|
||||||
You can respond to requests with a file using the `res.sendFile(path)` method. You can put it inside the `app.get('/', ...)` route handler. Behind the scenes, this method will set the appropriate headers to instruct your browser on how to handle the file you want to send, according to its type. Then it will read and send the file. This method needs an absolute file path. We recommend you to use the Node global variable `__dirname` to calculate the path like this:
|
通过 `res.sendFile(path)` 方法给请求响应一个文件, 可以把它放到路由处理 `app.get('/', ...)` 中。 在后台,这个方法会根据你想发送的文件的类型,设置适当的消息头信息来告诉浏览器如何处理它, 然后读取并发送文件, 此方法需要文件的绝对路径。 建议使用 Node. js 的全局变量 `__dirname` 来计算出这个文件的绝对路径:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
absolutePath = __dirname + relativePath/file.ext
|
absolutePath = __dirname + relativePath/file.ext
|
||||||
@ -16,13 +16,13 @@ absolutePath = __dirname + relativePath/file.ext
|
|||||||
|
|
||||||
# --instructions--
|
# --instructions--
|
||||||
|
|
||||||
Send the `/views/index.html` file as a response to GET requests to the `/` path. If you view your live app, you should see a big HTML heading (and a form that we will use later…), with no style applied.
|
发送文件 `/views/index.html` 作为 `/` 的 GET 请求的响应。 如果实时查看应用,你会看到一个大的 HTML 标题(以及我们稍后将使用的表单……),目前它们还没有任何样式。
|
||||||
|
|
||||||
**Note:** You can edit the solution of the previous challenge or create a new one. If you create a new solution, keep in mind that Express evaluates routes from top to bottom, and executes the handler for the first match. You have to comment out the preceding solution, or the server will keep responding with a string.
|
**注意:** 你可以编辑上一个挑战的解题代码,或者创建一个新的代码片段。 如果你创建一个新的代码片段,请记住 Express 会从上到下匹配路由,并执行第一个匹配的处理程序, 你必须注释掉前面的代码,否则服务器还是响应之前的字符串。
|
||||||
|
|
||||||
# --hints--
|
# --hints--
|
||||||
|
|
||||||
Your app should serve the file views/index.html
|
应用应该响应 views/index.html 文件
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) =>
|
(getUserInput) =>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: 587d7fb1367417b2b2512bf1
|
id: 587d7fb1367417b2b2512bf1
|
||||||
title: Serve JSON on a Specific Route
|
title: 在指定路由上提供 JSON 服务
|
||||||
challengeType: 2
|
challengeType: 2
|
||||||
forumTopicId: 301517
|
forumTopicId: 301517
|
||||||
dashedName: serve-json-on-a-specific-route
|
dashedName: serve-json-on-a-specific-route
|
||||||
@ -8,17 +8,17 @@ dashedName: serve-json-on-a-specific-route
|
|||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|
||||||
While an HTML server serves HTML, an API serves data. A <dfn>REST</dfn> (REpresentational State Transfer) API allows data exchange in a simple way, without the need for clients to know any detail about the server. The client only needs to know where the resource is (the URL), and the action it wants to perform on it (the verb). The GET verb is used when you are fetching some information, without modifying anything. These days, the preferred data format for moving information around the web is JSON. Simply put, JSON is a convenient way to represent a JavaScript object as a string, so it can be easily transmitted.
|
HTML 服务器提供 HTML 服务,而 API 提供数据服务。 <dfn>具象状态传输</dfn>(REST,REpresentational State Transfer)API 允许以简单的方式进行数据交换,对于客户端不必要知道服务器的细节。 客户只需要知道资源在哪里(URL),以及想执行的动作(动词)。 GET 动词常被用来获取无需修改的信息。 如今,网络上的移动数据首选格式是 JSON, 简而言之,JSON 是一种可以方便地用字符串表示 JavaScript 对象的方式,因此它很容易传输。
|
||||||
|
|
||||||
Let's create a simple API by creating a route that responds with JSON at the path `/json`. You can do it as usual, with the `app.get()` method. Inside the route handler, use the method `res.json()`, passing in an object as an argument. This method closes the request-response loop, returning the data. Behind the scenes, it converts a valid JavaScript object into a string, then sets the appropriate headers to tell your browser that you are serving JSON, and sends the data back. A valid object has the usual structure `{key: data}`. `data` can be a number, a string, a nested object or an array. `data` can also be a variable or the result of a function call, in which case it will be evaluated before being converted into a string.
|
我们来创建一个简单的 API,创建一个路径为 `/json` 且返回数据是 JSON 格式的路由, 可以像之前那样用 `app.get()` 方法来做。 然后在路由处理部分使用 `res.json()` 方法,并传入一个对象作为参数, 这个方法会结束请求响应循环(request-response loop),然后返回数据。 原来,一个有效的 JavaScript 对象会转化为字符串,然后会设置适当的消息头来告诉浏览器:“这是一个 JSON 数据”,最后将数据返回给客户端。 一个有效的对象通常是这种结构:`{key: data}`, `data` 可以是数字、字符串、嵌套对象或数组, `data` 也可以是变量或者函数返回值,在这种情况下,它们先求值再转成字符串。
|
||||||
|
|
||||||
# --instructions--
|
# --instructions--
|
||||||
|
|
||||||
Serve the object `{"message": "Hello json"}` as a response, in JSON format, to GET requests to the `/json` route. Then point your browser to `your-app-url/json`, you should see the message on the screen.
|
当向路由 `/json` 发送 GET 请求,将对象 `{"message": "Hello json"}` 以 JSON 格式返回给客户端, 浏览器访问 `your-app-url/json` 时,应该在屏幕上看到这个消息。
|
||||||
|
|
||||||
# --hints--
|
# --hints--
|
||||||
|
|
||||||
The endpoint `/json` should serve the json object `{"message": "Hello json"}`
|
访问端口 `/json` 应该返回一个 json 对象 `{"message": "Hello json"}`
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) =>
|
(getUserInput) =>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: 587d7fb0367417b2b2512bee
|
id: 587d7fb0367417b2b2512bee
|
||||||
title: Start a Working Express Server
|
title: 启动一个 Express 服务
|
||||||
challengeType: 2
|
challengeType: 2
|
||||||
forumTopicId: 301519
|
forumTopicId: 301519
|
||||||
dashedName: start-a-working-express-server
|
dashedName: start-a-working-express-server
|
||||||
@ -8,9 +8,9 @@ dashedName: start-a-working-express-server
|
|||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|
||||||
In the first two lines of the file `myApp.js`, you can see how easy it is to create an Express app object. This object has several methods, and you will learn many of them in these challenges. One fundamental method is `app.listen(port)`. It tells your server to listen on a given port, putting it in running state. For testing reasons, we need the app to be running in the background so we added this method in the `server.js` file for you.
|
在 `myApp.js` 文件的前两行中,你可以看到创建一个 Express 应用对象很简单。 这个对象有几种方法,在后面的挑战中将学习到其中的许多部分。 一个基础的方法是 `app.listen(port)`。 它处于运行状态时告诉服务器监听指定的端口。 出于测试的原因,需要应用在后台运行,所以在 `server.js` 中已经添加了这个方法。
|
||||||
|
|
||||||
Let’s serve our first string! In Express, routes takes the following structure: `app.METHOD(PATH, HANDLER)`. METHOD is an http method in lowercase. PATH is a relative path on the server (it can be a string, or even a regular expression). HANDLER is a function that Express calls when the route is matched. Handlers take the form `function(req, res) {...}`, where req is the request object, and res is the response object. For example, the handler
|
让我们在服务端输出第一个字符串! 在 Express 中,路由采用这种结构:`app.METHOD(PATH, HANDLER)`, METHOD 是 http 请求方法的小写形式, PATH 是服务器上的相对路径(它可以是一个字符串,甚至可以是正则表达式), HANDLER 是匹配路由时 Express 调用的函数, 处理函数采用这种形式:`function(req, res) {...}`,其中 req 是请求对象,res 是响应对象, 例如:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
function(req, res) {
|
function(req, res) {
|
||||||
@ -18,17 +18,17 @@ function(req, res) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
will serve the string 'Response String'.
|
将会响应一个字符串“Response String”。
|
||||||
|
|
||||||
# --instructions--
|
# --instructions--
|
||||||
|
|
||||||
Use the `app.get()` method to serve the string "Hello Express" to GET requests matching the `/` (root) path. Be sure that your code works by looking at the logs, then see the results in the preview if you are using Repl.it.
|
当 GET 请求 `/`(根路由 )时,使用 `app.get()` 方法响应一个“Hello Express”字符串。 通过查看日志确保代码正常运行,如果使用 Repl.it 可以在预览中查看结果。
|
||||||
|
|
||||||
**Note:** All the code for these lessons should be added in between the few lines of code we have started you off with.
|
**注意:** 这些课程的所有代码应该放在开始给出的几行代码之间。
|
||||||
|
|
||||||
# --hints--
|
# --hints--
|
||||||
|
|
||||||
Your app should serve the string 'Hello Express'
|
应用应该返回字符串“Hello Express”
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) =>
|
(getUserInput) =>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: 587d7fb2367417b2b2512bf7
|
id: 587d7fb2367417b2b2512bf7
|
||||||
title: Use body-parser to Parse POST Requests
|
title: 使用 body-parser 来解析 POST 请求
|
||||||
challengeType: 2
|
challengeType: 2
|
||||||
forumTopicId: 301520
|
forumTopicId: 301520
|
||||||
dashedName: use-body-parser-to-parse-post-requests
|
dashedName: use-body-parser-to-parse-post-requests
|
||||||
@ -8,9 +8,9 @@ dashedName: use-body-parser-to-parse-post-requests
|
|||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|
||||||
Besides GET, there is another common HTTP verb, it is POST. POST is the default method used to send client data with HTML forms. In REST convention, POST is used to send data to create new items in the database (a new user, or a new blog post). You don’t have a database in this project, but you are going to learn how to handle POST requests anyway.
|
除了 GET 还有另一个常见的 HTTP 动词,即 POST。 POST 是使用 HTML 表单发送客户端数据的默认方法。 在 REST 规范中,POST 常用于发送数据以在数据库中创建新项目(新用户或新博客文章)。 在这个项目中没有使用数据库,但下面将学习如何处理 POST 请求。
|
||||||
|
|
||||||
In these kind of requests, the data doesn’t appear in the URL, it is hidden in the request body. The body is a part of the HTTP request, also called the payload. Even though the data is not visible in the URL, this does not mean that it is private. To see why, look at the raw content of an HTTP POST request:
|
在这些类型的请求中,数据不会出现在 URL 中,而是隐藏在请求正文中。 请求正文也是 HTML 请求的一部分,被称为负载。 即使数据在 URL 中是不可见的,也不意味着它是私有的。 要了解原因,请观察 HTTP POST 请求的原始内容:
|
||||||
|
|
||||||
```http
|
```http
|
||||||
POST /path/subpath HTTP/1.0
|
POST /path/subpath HTTP/1.0
|
||||||
@ -22,17 +22,17 @@ Content-Length: 20
|
|||||||
name=John+Doe&age=25
|
name=John+Doe&age=25
|
||||||
```
|
```
|
||||||
|
|
||||||
As you can see, the body is encoded like the query string. This is the default format used by HTML forms. With Ajax, you can also use JSON to handle data having a more complex structure. There is also another type of encoding: multipart/form-data. This one is used to upload binary files. In this exercise, you will use a urlencoded body. To parse the data coming from POST requests, you have to install the `body-parser` package. This package allows you to use a series of middleware, which can decode data in different formats.
|
正如你所看到的,正文被编码成类似查询字符串的形式, 这是 HTML 表单使用的默认格式。 我们还可以通过 Ajax 使用 JSON 来处理具有更复杂结构的数据。 还有另一种类型的编码:multipart/form-data, 它被用来上传二进制文件。 在本练习中,我们将使用 URL 编码请求正文。 要解析来自 POST 请求的数据,你必须安装 `body-parser` 包, 这个包包含一套可以解码不同格式数据的中间件。
|
||||||
|
|
||||||
# --instructions--
|
# --instructions--
|
||||||
|
|
||||||
Install the `body-parser` module in your `package.json`. Then, `require` it at the top of the file. Store it in a variable named `bodyParser`. The middleware to handle urlencoded data is returned by `bodyParser.urlencoded({extended: false})`. Pass to `app.use()` the function returned by the previous method call. As usual, the middleware must be mounted before all the routes which need it.
|
在 `package.json` 中安装 `body-parser` 模块, 然后在文件顶部 `require` 进来, 用变量 `bodyParser` 保存它。 通过中间件的 `bodyParser.urlencoded({extended: false})` 方法处理 URL 编码数据, 将调用上个方法返回的函数传给 `app.use()`, 中间件通常挂载在所有需要它的路由之前。
|
||||||
|
|
||||||
**Note:** `extended=false` is a configuration option that tells the parser to use the classic encoding. When using it, values can be only strings or arrays. The extended version allows more data flexibility, but it is outmatched by JSON.
|
**注意:**`extended=false`是一个告诉解析器使用经典编码的配置选项, 当使用它时,值只能是字符串或者数组, 拓展版本数据更加灵活,但稍逊于 JSON。
|
||||||
|
|
||||||
# --hints--
|
# --hints--
|
||||||
|
|
||||||
The 'body-parser' middleware should be mounted
|
应该挂载“body-parser”中间件
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) =>
|
(getUserInput) =>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: 587d7fb3367417b2b2512bfc
|
id: 587d7fb3367417b2b2512bfc
|
||||||
title: Add a Description to Your package.json
|
title: 给 package.json 添加描述
|
||||||
challengeType: 2
|
challengeType: 2
|
||||||
forumTopicId: 301522
|
forumTopicId: 301522
|
||||||
dashedName: add-a-description-to-your-package-json
|
dashedName: add-a-description-to-your-package-json
|
||||||
@ -8,11 +8,11 @@ dashedName: add-a-description-to-your-package-json
|
|||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|
||||||
The next part of a good package.json file is the `description` field; where a short, but informative description about your project belongs.
|
一个好的 package.json 文件的下一部分就是 `description` 字段——简短精悍的的项目描述。
|
||||||
|
|
||||||
If you some day plan to publish a package to npm, this is the string that should sell your idea to the user when they decide whether to install your package or not. However, that’s not the only use case for the description, it’s a great way to summarize what a project does. It’s just as important in any Node.js project to help other developers, future maintainers or even your future self understand the project quickly.
|
如果你计划将来把这个包发布到 npm,请注意 description 字段的作用是告知用户这个包的用途,这样用户就可以决定是否要安装你发布的包。 然而,这并不是使用描述的唯一场景:它也是一种很好的总结项目的方式, 可以帮助其它开发者、维护者甚至自己在未来快速地了解项目,对于任何一个 Node.js 项目来说都非常重要。
|
||||||
|
|
||||||
Regardless of what you plan for your project, a description is definitely recommended. Here's an example:
|
无论项目计划是什么,都建议使用描述。 类似这样:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
"description": "A project that does something awesome",
|
"description": "A project that does something awesome",
|
||||||
@ -20,13 +20,13 @@ Regardless of what you plan for your project, a description is definitely recomm
|
|||||||
|
|
||||||
# --instructions--
|
# --instructions--
|
||||||
|
|
||||||
Add a `description` to the package.json file of your project.
|
给项目的 package.json 文件添加描述(`description`)。
|
||||||
|
|
||||||
**Note:** Remember to use double-quotes for field-names (") and commas (,) to separate fields.
|
**注意:** 请记住使用双引号(")包裹字段名并且使用逗号(,)分隔字段。
|
||||||
|
|
||||||
# --hints--
|
# --hints--
|
||||||
|
|
||||||
package.json should have a valid "description" key
|
package.json 应该包含一个有效的“description”键
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) =>
|
(getUserInput) =>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: 587d7fb4367417b2b2512bfe
|
id: 587d7fb4367417b2b2512bfe
|
||||||
title: Add a License to Your package.json
|
title: 给 package.json 添加许可证
|
||||||
challengeType: 2
|
challengeType: 2
|
||||||
forumTopicId: 301523
|
forumTopicId: 301523
|
||||||
dashedName: add-a-license-to-your-package-json
|
dashedName: add-a-license-to-your-package-json
|
||||||
@ -8,9 +8,9 @@ dashedName: add-a-license-to-your-package-json
|
|||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|
||||||
The `license` field is where you inform users of what they are allowed to do with your project.
|
`license` 字段将告知用户允许他们拿这个项目干什么。
|
||||||
|
|
||||||
Some common licenses for open source projects include MIT and BSD. License information is not required, and copyright laws in most countries will give you ownership of what you create by default. However, it’s always a good practice to explicitly state what users can and can’t do. Here's an example of the license field:
|
开源项目常见的协议有 MIT 和 BSD 等。 许可证信息并不是必须的。 大多数国家的版权法会默认让你拥有自己创作的作品的所有权。 但是,明确说明用户可以做什么和不能做什么会是一个很好的做法。 这里有一个 license 字段的例子:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@ -18,11 +18,11 @@ Some common licenses for open source projects include MIT and BSD. License infor
|
|||||||
|
|
||||||
# --instructions--
|
# --instructions--
|
||||||
|
|
||||||
Fill the `license` field in the package.json file of your project as you find suitable.
|
在项目的 package.json 文件中补充合适的 `license` 字段。
|
||||||
|
|
||||||
# --hints--
|
# --hints--
|
||||||
|
|
||||||
package.json should have a valid "license" key
|
package.json 应该包含一个有效的“license”键
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) =>
|
(getUserInput) =>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: 587d7fb4367417b2b2512bff
|
id: 587d7fb4367417b2b2512bff
|
||||||
title: Add a Version to Your package.json
|
title: 给 package.json 添加版本号
|
||||||
challengeType: 2
|
challengeType: 2
|
||||||
forumTopicId: 301525
|
forumTopicId: 301525
|
||||||
dashedName: add-a-version-to-your-package-json
|
dashedName: add-a-version-to-your-package-json
|
||||||
@ -8,7 +8,7 @@ dashedName: add-a-version-to-your-package-json
|
|||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|
||||||
A `version` is one of the required fields of your package.json file. This field describes the current version of your project. Here's an example:
|
`version` 是 package.json 文件中必填字段之一, 这个字段描述了当前项目的版本, 如:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
@ -16,11 +16,11 @@ A `version` is one of the required fields of your package.json file. This field
|
|||||||
|
|
||||||
# --instructions--
|
# --instructions--
|
||||||
|
|
||||||
Add a `version` to the package.json file of your project.
|
给 package.json 文件添加项目的版本号(`version`)。
|
||||||
|
|
||||||
# --hints--
|
# --hints--
|
||||||
|
|
||||||
package.json should have a valid "version" key
|
package.json 应该包含一个有效的 “version” 键
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) =>
|
(getUserInput) =>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: 587d7fb4367417b2b2512bfd
|
id: 587d7fb4367417b2b2512bfd
|
||||||
title: Add Keywords to Your package.json
|
title: 给 package.json 添加关键词
|
||||||
challengeType: 2
|
challengeType: 2
|
||||||
forumTopicId: 301526
|
forumTopicId: 301526
|
||||||
dashedName: add-keywords-to-your-package-json
|
dashedName: add-keywords-to-your-package-json
|
||||||
@ -8,23 +8,23 @@ dashedName: add-keywords-to-your-package-json
|
|||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|
||||||
The `keywords` field is where you can describe your project using related keywords. Here's an example:
|
在 `keywords` 字段中可以使用相关的关键字描述项目。 例如:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
"keywords": [ "descriptive", "related", "words" ],
|
"keywords": [ "descriptive", "related", "words" ],
|
||||||
```
|
```
|
||||||
|
|
||||||
As you can see, this field is structured as an array of double-quoted strings.
|
正如你所见的,这个字段的结构是一个由双引号字符串组成的数组。
|
||||||
|
|
||||||
# --instructions--
|
# --instructions--
|
||||||
|
|
||||||
Add an array of suitable strings to the `keywords` field in the package.json file of your project.
|
在 package.json 文件中,给 `keywords` 字段添加一个由适当的字符串组成的数组。
|
||||||
|
|
||||||
One of the keywords should be "freecodecamp".
|
“freecodecamp”应该是关键词之一。
|
||||||
|
|
||||||
# --hints--
|
# --hints--
|
||||||
|
|
||||||
package.json should have a valid "keywords" key
|
package.json 应该有一个有效的“keywords”键
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) =>
|
(getUserInput) =>
|
||||||
@ -39,7 +39,7 @@ package.json should have a valid "keywords" key
|
|||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
"keywords" field should be an Array
|
“keywords”字段应该是一个数组
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) =>
|
(getUserInput) =>
|
||||||
@ -54,7 +54,7 @@ package.json should have a valid "keywords" key
|
|||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
"keywords" should include "freecodecamp"
|
“keywords”中应该包含关键词“freecodecamp”
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) =>
|
(getUserInput) =>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: 587d7fb4367417b2b2512c00
|
id: 587d7fb4367417b2b2512c00
|
||||||
title: Expand Your Project with External Packages from npm
|
title: 使用 npm 的外部包扩展项目
|
||||||
challengeType: 2
|
challengeType: 2
|
||||||
forumTopicId: 301527
|
forumTopicId: 301527
|
||||||
dashedName: expand-your-project-with-external-packages-from-npm
|
dashedName: expand-your-project-with-external-packages-from-npm
|
||||||
@ -8,9 +8,9 @@ dashedName: expand-your-project-with-external-packages-from-npm
|
|||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|
||||||
One of the biggest reasons to use a package manager, is their powerful dependency management. Instead of manually having to make sure that you get all dependencies whenever you set up a project on a new computer, npm automatically installs everything for you. But how can npm know exactly what your project needs? Meet the `dependencies` section of your package.json file.
|
强大的依赖管理特性是使用包管理器的最大原因之一。 每当在新的计算机上开始一个项目时,无需手动,npm 会自动安装所有的依赖项。 但是 npm 如何准确地知道项目需要哪些依赖呢? 来看看 package.json 文件中 `dependencies` 这一部分。
|
||||||
|
|
||||||
In this section, packages your project requires are stored using the following format:
|
在这部分,你的项目需要按照下面这种格式来存储依赖包:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -22,13 +22,13 @@ In this section, packages your project requires are stored using the following f
|
|||||||
|
|
||||||
# --instructions--
|
# --instructions--
|
||||||
|
|
||||||
Add version "2.14.0" of the "moment" package to the `dependencies` field of your package.json file.
|
在 package.json 文件的 `dependencies` 字段中添加一个版本号为“2.14.0”的“moment”包。
|
||||||
|
|
||||||
**Note:** Moment is a handy library for working with time and dates.
|
**注意:** Moment 是一个非常方便地用来处理时间和日期的库。
|
||||||
|
|
||||||
# --hints--
|
# --hints--
|
||||||
|
|
||||||
"dependencies" should include "moment"
|
“dependencies”应该包含“moment”
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) =>
|
(getUserInput) =>
|
||||||
@ -47,7 +47,7 @@ Add version "2.14.0" of the "moment" package to the `dependencies` field of your
|
|||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
"moment" version should be "2.14.0"
|
“moment”的版本应该是“2.14.0”
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) =>
|
(getUserInput) =>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: 587d7fb5367417b2b2512c01
|
id: 587d7fb5367417b2b2512c01
|
||||||
title: Manage npm Dependencies By Understanding Semantic Versioning
|
title: 通过语义化版本来管理 npm 依赖关系
|
||||||
challengeType: 2
|
challengeType: 2
|
||||||
forumTopicId: 301529
|
forumTopicId: 301529
|
||||||
dashedName: manage-npm-dependencies-by-understanding-semantic-versioning
|
dashedName: manage-npm-dependencies-by-understanding-semantic-versioning
|
||||||
@ -8,23 +8,23 @@ dashedName: manage-npm-dependencies-by-understanding-semantic-versioning
|
|||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|
||||||
`Versions` of the npm packages in the dependencies section of your package.json file follow what’s called Semantic Versioning (SemVer), an industry standard for software versioning aiming to make it easier to manage dependencies. Libraries, frameworks or other tools published on npm should use SemVer in order to clearly communicate what kind of changes projects can expect if they update.
|
在 package.json 文件的依赖项中,npm 包的 `Versions` 遵循语义化版本(SemVer,Semantic Versioning),它是一种旨在使管理依赖项更加容易的软件版本控制的行业标准。 在 npm 上发布的库、框架或其它工具都应该使用语义化版本,以便让用户清晰地知道如果项目升级将带来哪些改变。
|
||||||
|
|
||||||
Knowing SemVer can be useful when you develop software that uses external dependencies (which you almost always do). One day, your understanding of these numbers will save you from accidentally introducing breaking changes to your project without understanding why things that worked yesterday suddenly don’t work today. This is how Semantic Versioning works according to the official website:
|
在使用外部依赖项(大多数情况都是这样)进行软件开发时,了解语义化版本会很有用。 这些数字保存着项目的偶然发生的破坏性改变,不会让人对项目昨天还正常,今天却无法运行而百思不解。 根据官网,这是语义化版本的工作方式:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
"package": "MAJOR.MINOR.PATCH"
|
"package": "MAJOR.MINOR.PATCH"
|
||||||
```
|
```
|
||||||
|
|
||||||
The MAJOR version should increment when you make incompatible API changes. The MINOR version should increment when you add functionality in a backwards-compatible manner. The PATCH version should increment when you make backwards-compatible bug fixes. This means that PATCHes are bug fixes and MINORs add new features but neither of them break what worked before. Finally, MAJORs add changes that won’t work with earlier versions.
|
当做了不兼容的 API 修改,应该增加主版本号(MAJOR); 当新增了向下兼容的新功能时,应该增加次版本号(MINOR); 当修复了向下兼容的 bug 时,应该增加修订号(PATCH)。 这意味着修订号是用来修复错误的,次版本号则是添加了新功能,但它们都没有破坏之前的功能。 主版本号(MAJOR)是添加了不兼容早期版本的更改。
|
||||||
|
|
||||||
# --instructions--
|
# --instructions--
|
||||||
|
|
||||||
In the dependencies section of your package.json file, change the `version` of moment to match MAJOR version 2, MINOR version 10 and PATCH version 2
|
在 package.json 文件的依赖项中,修改 moment 的`version`,让它的主版本是 2,次版本号是 10,修订号是 2。
|
||||||
|
|
||||||
# --hints--
|
# --hints--
|
||||||
|
|
||||||
"dependencies" should include "moment"
|
“dependencies”字段应该包含“moment”
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) =>
|
(getUserInput) =>
|
||||||
@ -43,7 +43,7 @@ In the dependencies section of your package.json file, change the `version` of m
|
|||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
"moment" version should be "2.10.2"
|
“moment”的版本号应该是“2.10.2”
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) =>
|
(getUserInput) =>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: 587d7fb5367417b2b2512c04
|
id: 587d7fb5367417b2b2512c04
|
||||||
title: Remove a Package from Your Dependencies
|
title: 从依赖项中删除依赖包
|
||||||
challengeType: 2
|
challengeType: 2
|
||||||
forumTopicId: 301530
|
forumTopicId: 301530
|
||||||
dashedName: remove-a-package-from-your-dependencies
|
dashedName: remove-a-package-from-your-dependencies
|
||||||
@ -8,21 +8,21 @@ dashedName: remove-a-package-from-your-dependencies
|
|||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|
||||||
You have now tested a few ways you can manage dependencies of your project by using the package.json's dependencies section. You have also included external packages by adding them to the file and even told npm what types of versions you want, by using special characters such as the tilde or the caret.
|
已经尝试过一些通过项目 package.json 文件中依赖项管理依赖的方式了, 也添加了一些外部的依赖包到项目中,甚至通过一些特殊的字符比如波浪号或者脱字符来告诉 npm 想要的版本类型。
|
||||||
|
|
||||||
But what if you want to remove an external package that you no longer need? You might already have guessed it, just remove the corresponding key-value pair for that package from your dependencies.
|
但是,如果想要删除不再需要的依赖包,该怎么办呢? 可能已经猜到了——只需要从依赖项中删除相应的键值对就行了。
|
||||||
|
|
||||||
This same method applies to removing other fields in your package.json as well
|
同样的方法也适用于删除 package.json 中的其它字段。
|
||||||
|
|
||||||
# --instructions--
|
# --instructions--
|
||||||
|
|
||||||
Remove the moment package from your dependencies.
|
从依赖项中删除 moment 依赖包。
|
||||||
|
|
||||||
**Note:** Make sure you have the right amount of commas after removing it.
|
**注意:**删除依赖包后,确保逗号数量正确。
|
||||||
|
|
||||||
# --hints--
|
# --hints--
|
||||||
|
|
||||||
"dependencies" should not include "moment"
|
“dependencies”字段不包含“moment”。
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) =>
|
(getUserInput) =>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: 587d7fb5367417b2b2512c03
|
id: 587d7fb5367417b2b2512c03
|
||||||
title: Use the Caret-Character to Use the Latest Minor Version of a Dependency
|
title: 用脱字符(^)来使用依赖项的最新次要版本
|
||||||
challengeType: 2
|
challengeType: 2
|
||||||
forumTopicId: 301531
|
forumTopicId: 301531
|
||||||
dashedName: use-the-caret-character-to-use-the-latest-minor-version-of-a-dependency
|
dashedName: use-the-caret-character-to-use-the-latest-minor-version-of-a-dependency
|
||||||
@ -8,25 +8,25 @@ dashedName: use-the-caret-character-to-use-the-latest-minor-version-of-a-depende
|
|||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|
||||||
Similar to how the tilde we learned about in the last challenge allows npm to install the latest PATCH for a dependency, the caret (`^`) allows npm to install future updates as well. The difference is that the caret will allow both MINOR updates and PATCHes.
|
和上一个挑战中我们学到的用波浪号来安装最新的修订版依赖一样,脱字符(`^`)也允许 npm 来安装功能更新。 它们的不同之处在于:脱字符允许次版本和修订版更新。
|
||||||
|
|
||||||
Your current version of moment should be "~2.10.2" which allows npm to install to the latest 2.10.x version. If you were to use the caret (^) as a version prefix instead, npm would be allowed to update to any 2.x.x version.
|
现在项目中的 moment 依赖包的版本应该是“~2.10.2”,这意味着 npm 可以安装最新的 2.10.x 版的 moment, 如果使用脱字符(^)来替换版本号的前缀,那么 npm 可以将 moment 升级安装到任何 2.x.x 的版本。
|
||||||
|
|
||||||
```json
|
```json
|
||||||
"package": "^1.3.8"
|
"package": "^1.3.8"
|
||||||
```
|
```
|
||||||
|
|
||||||
This would allow updates to any 1.x.x version of the package.
|
这会将依赖包更新到任意的 1.x.x 版本。
|
||||||
|
|
||||||
# --instructions--
|
# --instructions--
|
||||||
|
|
||||||
Use the caret (`^`) to prefix the version of moment in your dependencies and allow npm to update it to any new MINOR release.
|
在依赖项中,使用脱字符(`^`)为 moment 的版本添加前缀,允许 npm 更新依赖包到任意新的次版本。
|
||||||
|
|
||||||
**Note:** The version numbers themselves should not be changed.
|
**注意:**原来的版本号不用更改。
|
||||||
|
|
||||||
# --hints--
|
# --hints--
|
||||||
|
|
||||||
"dependencies" should include "moment"
|
“dependencies”字段中应包含“moment”
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) =>
|
(getUserInput) =>
|
||||||
@ -45,7 +45,7 @@ Use the caret (`^`) to prefix the version of moment in your dependencies and all
|
|||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
"moment" version should match "^2.x.x"
|
“moment”的版本应是“^2.x.x”
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) =>
|
(getUserInput) =>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: 587d7fb5367417b2b2512c02
|
id: 587d7fb5367417b2b2512c02
|
||||||
title: Use the Tilde-Character to Always Use the Latest Patch Version of a Dependency
|
title: 用波浪号维持依赖项的最新修订号
|
||||||
challengeType: 2
|
challengeType: 2
|
||||||
forumTopicId: 301532
|
forumTopicId: 301532
|
||||||
dashedName: use-the-tilde-character-to-always-use-the-latest-patch-version-of-a-dependency
|
dashedName: use-the-tilde-character-to-always-use-the-latest-patch-version-of-a-dependency
|
||||||
@ -8,9 +8,9 @@ dashedName: use-the-tilde-character-to-always-use-the-latest-patch-version-of-a-
|
|||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|
||||||
In the last challenge, you told npm to only include a specific version of a package. That’s a useful way to freeze your dependencies if you need to make sure that different parts of your project stay compatible with each other. But in most use cases, you don’t want to miss bug fixes since they often include important security patches and (hopefully) don’t break things in doing so.
|
在上一个挑战中,npm 只包含特定版本的依赖包。 如果想让项目各个部分保持相互兼容,锁定依赖包版本是一个行之有效的办法。 但是大多数情况下,我们并不希望错过依赖项的问题修复,因为它们通常包含重要的安全补丁,而且它们理论上也会兼容我们既有的代码。
|
||||||
|
|
||||||
To allow an npm dependency to update to the latest PATCH version, you can prefix the dependency’s version with the tilde (`~`) character. Here's an example of how to allow updates to any 1.3.x version.
|
可以在依赖项的版本号前加一个波浪号(`~`),以让 npm 依赖项更新到最新的修订版。 这里有一个允许升级到任何 1.3.x 的例子:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
"package": "~1.3.8"
|
"package": "~1.3.8"
|
||||||
@ -18,15 +18,15 @@ To allow an npm dependency to update to the latest PATCH version, you can prefix
|
|||||||
|
|
||||||
# --instructions--
|
# --instructions--
|
||||||
|
|
||||||
In the package.json file, your current rule for how npm may upgrade moment is to use a specific version (2.10.2). But now, you want to allow the latest 2.10.x version.
|
在 package.json 文件中,当前规则是 npm 将 moment 升级到特定版本(2.10.2)。 但是现在,要允许使用最新的 2.10.x 版本。
|
||||||
|
|
||||||
Use the tilde (`~`) character to prefix the version of moment in your dependencies, and allow npm to update it to any new PATCH release.
|
在依赖项中,给 moment 的版本号添加波浪号(`~`)前缀,允许 npm 将其更新为最新的修订版。
|
||||||
|
|
||||||
**Note:** The version numbers themselves should not be changed.
|
**注意:**原来的版本号不用更改。
|
||||||
|
|
||||||
# --hints--
|
# --hints--
|
||||||
|
|
||||||
"dependencies" should include "moment"
|
“dependencies”应该包含“moment”
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) =>
|
(getUserInput) =>
|
||||||
@ -45,7 +45,7 @@ Use the tilde (`~`) character to prefix the version of moment in your dependenci
|
|||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
"moment" version should match "~2.10.2"
|
“moment”的版本号应该是“~2.10.2”
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) =>
|
(getUserInput) =>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: 587d7fb9367417b2b2512c12
|
id: 587d7fb9367417b2b2512c12
|
||||||
title: Chain Search Query Helpers to Narrow Search Results
|
title: 通过链式调用辅助查询函数来缩小搜索结果
|
||||||
challengeType: 2
|
challengeType: 2
|
||||||
forumTopicId: 301533
|
forumTopicId: 301533
|
||||||
dashedName: chain-search-query-helpers-to-narrow-search-results
|
dashedName: chain-search-query-helpers-to-narrow-search-results
|
||||||
@ -8,15 +8,15 @@ dashedName: chain-search-query-helpers-to-narrow-search-results
|
|||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|
||||||
If you don’t pass the callback as the last argument to `Model.find()` (or to the other search methods), the query is not executed. You can store the query in a variable for later use. This kind of object enables you to build up a query using chaining syntax. The actual db search is executed when you finally chain the method `.exec()`. You always need to pass your callback to this last method. There are many query helpers, here we'll use the most commonly used.
|
如果不给 `Model.find()`(或者别的搜索方法)的最后一个参数传入回调函数, 查询将不会执行。 可以将查询条件存储在变量中供以后使用, 也可以通过链式调用这类变量来构建新的查询字段。 实际的数据库操作会在最后调用 `.exec()` 方法时执行。 必须把回调函数传给最后一个方法。 Mongoose 提供了许多辅助查询函数, 这里使用最常见的一种。
|
||||||
|
|
||||||
# --instructions--
|
# --instructions--
|
||||||
|
|
||||||
Modify the `queryChain` function to find people who like the food specified by the variable named `foodToSearch`. Sort them by `name`, limit the results to two documents, and hide their age. Chain `.find()`, `.sort()`, `.limit()`, `.select()`, and then `.exec()`. Pass the `done(err, data)` callback to `exec()`.
|
修改 `queryChain` 函数来查询喜欢 `foodToSearch` 食物的人。 同时,需要将查询结果按 `name` 属性排序, 查询结果应限制在两个 document 内,并隐藏 age 属性。 请链式调用 `.find()`、`.sort()`、`.limit()` 和 `.select()`,并在最后调用 `.exec()`, 并将 `done(err, data)` 回调函数传入 `exec()`。
|
||||||
|
|
||||||
# --hints--
|
# --hints--
|
||||||
|
|
||||||
Chaining query helpers should succeed
|
应该成功地链式调用辅助查询函数。
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) =>
|
(getUserInput) =>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: 587d7fb6367417b2b2512c07
|
id: 587d7fb6367417b2b2512c07
|
||||||
title: Create a Model
|
title: 创建一个模型(Model)
|
||||||
challengeType: 2
|
challengeType: 2
|
||||||
forumTopicId: 301535
|
forumTopicId: 301535
|
||||||
dashedName: create-a-model
|
dashedName: create-a-model
|
||||||
@ -8,13 +8,13 @@ dashedName: create-a-model
|
|||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|
||||||
**C**RUD Part I - CREATE
|
**C**RUD 第一小节——CREATE
|
||||||
|
|
||||||
First of all we need a Schema. Each schema maps to a MongoDB collection. It defines the shape of the documents within that collection. Schemas are building block for Models. They can be nested to create complex models, but in this case we'll keep things simple. A model allows you to create instances of your objects, called documents.
|
首先,我们需要一个 Schema, 每一个 Schema 都对应一个 MongoDB 的 collection, 并且在相应的 collection 里定义 documents 的“样子”。 Schema 用于组成模型(Model), 我们甚至可以通过嵌套 Schema 来创建复杂的模型。目前我们先从简。 我们可以根据模型创建实例,模型实例化后的对象称为 documents。
|
||||||
|
|
||||||
Repl.it is a real server, and in real servers the interactions with the database happen in handler functions. These functions are executed when some event happens (e.g. someone hits an endpoint on your API). We’ll follow the same approach in these exercises. The `done()` function is a callback that tells us that we can proceed after completing an asynchronous operation such as inserting, searching, updating, or deleting. It's following the Node convention, and should be called as `done(null, data)` on success, or `done(err)` on error.
|
Repl.it 是一个真实的服务器。正式的服务通过 handler 函数和数据库交互。 这些函数会在特定事件(比如有人调用了我们的服务器 API)发生时执行。 接下来的挑战题目即是以此为基础。 `done()` 是一个回调函数,它的作用是在一个异步操作(比如对数据库进行插入、查询、更新或删除)执行完成时,通知我们可以继续执行后续的其它代码。 这与 Node.js 中的处理方式十分类似,在 Node.js 中,我们会在(异步操作)成功时调用 `done(null, data)`,在失败时调用 `done(err)`。
|
||||||
|
|
||||||
Warning - When interacting with remote services, errors may occur!
|
注意:与远程服务器进行交互时,我们需要考虑到发生错误的可能!
|
||||||
|
|
||||||
```js
|
```js
|
||||||
/* Example */
|
/* Example */
|
||||||
@ -28,7 +28,7 @@ const someFunc = function(done) {
|
|||||||
|
|
||||||
# --instructions--
|
# --instructions--
|
||||||
|
|
||||||
Create a person schema called `personSchema` having this prototype:
|
按下面的原型信息创建一个名为 `personSchema` 的 schema:
|
||||||
|
|
||||||
```markup
|
```markup
|
||||||
- Person Prototype -
|
- Person Prototype -
|
||||||
@ -38,13 +38,13 @@ age : number
|
|||||||
favoriteFoods : array of strings (*)
|
favoriteFoods : array of strings (*)
|
||||||
```
|
```
|
||||||
|
|
||||||
Use the Mongoose basic schema types. If you want you can also add more fields, use simple validators like required or unique, and set default values. See the [Mongoose docs](http://mongoosejs.com/docs/guide.html).
|
采用 Mongoose 基础 schema 类型。 你如果还想添加更多的键,就请使用 required 或 unique 等简单的验证器(validators),并设置默认值。 详情请参考 [Mongoose 文档](http://mongoosejs.com/docs/guide.html)。
|
||||||
|
|
||||||
Now, create a model called `Person` from the `personSchema`.
|
请从 `personSchema` 创建一个名为 `Person` 的 model。
|
||||||
|
|
||||||
# --hints--
|
# --hints--
|
||||||
|
|
||||||
Creating an instance from a mongoose schema should succeed
|
应当成功地通过 Mongoose schema 创建实例
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) =>
|
(getUserInput) =>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: 587d7fb6367417b2b2512c09
|
id: 587d7fb6367417b2b2512c09
|
||||||
title: Create and Save a Record of a Model
|
title: 创建并保存一条 Model 记录
|
||||||
challengeType: 2
|
challengeType: 2
|
||||||
forumTopicId: 301536
|
forumTopicId: 301536
|
||||||
dashedName: create-and-save-a-record-of-a-model
|
dashedName: create-and-save-a-record-of-a-model
|
||||||
@ -8,11 +8,11 @@ dashedName: create-and-save-a-record-of-a-model
|
|||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|
||||||
In this challenge you will have to create and save a record of a model.
|
在这个挑战中,你需要创建并保存一条模型数据。
|
||||||
|
|
||||||
# --instructions--
|
# --instructions--
|
||||||
|
|
||||||
Within the `createAndSavePerson` function, create a document instance using the `Person` model constructor you built before. Pass to the constructor an object having the fields `name`, `age`, and `favoriteFoods`. Their types must conform to the ones in the `personSchema`. Then, call the method `document.save()` on the returned document instance. Pass to it a callback using the Node convention. This is a common pattern; all the following CRUD methods take a callback function like this as the last argument.
|
在 `createAndSavePerson` 函数中,用我们在上一个挑战中写好的 `Person` 构造函数创建 document 实例, 将包含 `name`、`age` 和 `favoriteFoods` 的对象传给构造函数, 这些属性的数据类型必须符合我们在 `personSchema` 中定义的类型。 然后在返回的 document 实例上调用方法 `document.save()`。 同时,按 Node.js 的方式为它传一个回调函数。 这是一种常见模式,以下所有CRUD方法都将这样的回调函数作为最后一个参数。
|
||||||
|
|
||||||
```js
|
```js
|
||||||
/* Example */
|
/* Example */
|
||||||
@ -25,7 +25,7 @@ person.save(function(err, data) {
|
|||||||
|
|
||||||
# --hints--
|
# --hints--
|
||||||
|
|
||||||
Creating and saving a db item should succeed
|
应成功地创建数据并保存一条数据到数据库
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) =>
|
(getUserInput) =>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: 587d7fb7367417b2b2512c0a
|
id: 587d7fb7367417b2b2512c0a
|
||||||
title: Create Many Records with model.create()
|
title: 使用 model.create() 创建多条记录
|
||||||
challengeType: 2
|
challengeType: 2
|
||||||
forumTopicId: 301537
|
forumTopicId: 301537
|
||||||
dashedName: create-many-records-with-model-create
|
dashedName: create-many-records-with-model-create
|
||||||
@ -8,17 +8,17 @@ dashedName: create-many-records-with-model-create
|
|||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|
||||||
Sometimes you need to create many instances of your models, e.g. when seeding a database with initial data. `Model.create()` takes an array of objects like `[{name: 'John', ...}, {...}, ...]` as the first argument, and saves them all in the db.
|
在一些情况下,比如进行数据库初始化,你会需要创建很多 model 实例来用作初始数据。 `Model.create()` 接受一组像 `[{name: 'John', ...}, {...}, ...]` 的数组作为第一个参数,并将其保存到数据库。
|
||||||
|
|
||||||
# --instructions--
|
# --instructions--
|
||||||
|
|
||||||
Modify the `createManyPeople` function to create many people using `Model.create()` with the argument `arrayOfPeople`.
|
修改 `createManyPeople` 方法,使用 `arrayOfPeople` 作为 `Model.create()` 的参数来创建多个 people 实例。
|
||||||
|
|
||||||
**Note:** You can reuse the model you instantiated in the previous exercise.
|
**注意:** 你可以使用在上一个挑战中创建的 model 来完成当前挑战。
|
||||||
|
|
||||||
# --hints--
|
# --hints--
|
||||||
|
|
||||||
Creating many db items at once should succeed
|
应当成功地一次性创建多条数据
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) =>
|
(getUserInput) =>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: 587d7fb8367417b2b2512c11
|
id: 587d7fb8367417b2b2512c11
|
||||||
title: Delete Many Documents with model.remove()
|
title: 使用 model.remove() 删除多个 document
|
||||||
challengeType: 2
|
challengeType: 2
|
||||||
forumTopicId: 301538
|
forumTopicId: 301538
|
||||||
dashedName: delete-many-documents-with-model-remove
|
dashedName: delete-many-documents-with-model-remove
|
||||||
@ -8,17 +8,17 @@ dashedName: delete-many-documents-with-model-remove
|
|||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|
||||||
`Model.remove()` is useful to delete all the documents matching given criteria.
|
`Model.remove()` 可以用于删除符合给定匹配条件的所有 document。
|
||||||
|
|
||||||
# --instructions--
|
# --instructions--
|
||||||
|
|
||||||
Modify the `removeManyPeople` function to delete all the people whose name is within the variable `nameToRemove`, using `Model.remove()`. Pass it to a query document with the `name` field set, and a callback.
|
修改 `removeManyPeople` 函数,使用 `nameToRemove` 删除所有姓名是变量 `Model.remove()` 的人。 给它传入一个带有 `name` 字段的查询 document 和一个回调函数。
|
||||||
|
|
||||||
**Note:** The `Model.remove()` doesn’t return the deleted document, but a JSON object containing the outcome of the operation, and the number of items affected. Don’t forget to pass it to the `done()` callback, since we use it in tests.
|
**注意:** `Model.remove()` 不会返回被删除的 document,而是会返回一个包含操作结果以及受影响的数据数量的 JSON 对象。 不要忘记将它传入 `done()` 回调函数,因为我们需要在挑战的测试中调用它。
|
||||||
|
|
||||||
# --hints--
|
# --hints--
|
||||||
|
|
||||||
Deleting many items at once should succeed
|
应一次性成功删除多条数据
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) =>
|
(getUserInput) =>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: 587d7fb8367417b2b2512c10
|
id: 587d7fb8367417b2b2512c10
|
||||||
title: Delete One Document Using model.findByIdAndRemove
|
title: 使用 model.findByIdAndRemove 删除一个 document
|
||||||
challengeType: 2
|
challengeType: 2
|
||||||
forumTopicId: 301539
|
forumTopicId: 301539
|
||||||
dashedName: delete-one-document-using-model-findbyidandremove
|
dashedName: delete-one-document-using-model-findbyidandremove
|
||||||
@ -8,15 +8,15 @@ dashedName: delete-one-document-using-model-findbyidandremove
|
|||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|
||||||
`findByIdAndRemove` and `findOneAndRemove` are like the previous update methods. They pass the removed document to the db. As usual, use the function argument `personId` as the search key.
|
`findByIdAndRemove` 和 `findOneAndRemove` 类似于我们之前的更新方法, 它们将被删除的 document 传给数据库。 和之前一样,使用函数参数 `personId` 作为查询关键字。
|
||||||
|
|
||||||
# --instructions--
|
# --instructions--
|
||||||
|
|
||||||
Modify the `removeById` function to delete one person by the person's `_id`. You should use one of the methods `findByIdAndRemove()` or `findOneAndRemove()`.
|
修改 `removeById` 函数,通过 `_id` 删除一个人的数据, 可以使用 `findByIdAndRemove()` 或 `findOneAndRemove()` 方法。
|
||||||
|
|
||||||
# --hints--
|
# --hints--
|
||||||
|
|
||||||
Deleting an item should succeed
|
应当成功地删除一条数据
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) =>
|
(getUserInput) =>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: 587d7fb8367417b2b2512c0e
|
id: 587d7fb8367417b2b2512c0e
|
||||||
title: 'Perform Classic Updates by Running Find, Edit, then Save'
|
title: '通过执行查询、编辑、保存来执行经典更新流程'
|
||||||
challengeType: 2
|
challengeType: 2
|
||||||
forumTopicId: 301541
|
forumTopicId: 301541
|
||||||
dashedName: perform-classic-updates-by-running-find-edit-then-save
|
dashedName: perform-classic-updates-by-running-find-edit-then-save
|
||||||
@ -8,17 +8,17 @@ dashedName: perform-classic-updates-by-running-find-edit-then-save
|
|||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|
||||||
In the good old days, this was what you needed to do if you wanted to edit a document, and be able to use it somehow (e.g. sending it back in a server response). Mongoose has a dedicated updating method: `Model.update()`. It is bound to the low-level mongo driver. It can bulk-edit many documents matching certain criteria, but it doesn’t send back the updated document, only a 'status' message. Furthermore, it makes model validations difficult, because it just directly calls the mongo driver.
|
在过去,如果想要编辑 document 并以某种方式使用它(比如放到服务器的返回数据中),就必须执行查找、编辑和保存。 Mongoose 有一个专用的更新方法 `Model.update()`, 它与底层的 mongo 驱动绑定。 通过这个方法,我们可以批量编辑符合特定条件的多个 document。但问题在于,这个方法不会返回更新后的 document,而是返回状态信息。 此外,它直接调用 mongo 的底层驱动,让处理 model 的验证变得更加棘手。
|
||||||
|
|
||||||
# --instructions--
|
# --instructions--
|
||||||
|
|
||||||
Modify the `findEditThenSave` function to find a person by `_id` (use any of the above methods) with the parameter `personId` as search key. Add `"hamburger"` to the list of the person's `favoriteFoods` (you can use `Array.push()`). Then - inside the find callback - `save()` the updated `Person`.
|
在这个挑战中,请使用参数 `personId` 作为字段,修改 `findEditThenSave` 方法,以在数据库中通过 `_id` 找到相应的 person(你可以使用之前挑战中的任何一种方法)。 将 `"hamburger"` 添加到它的 `favoriteFoods` 清单中(你可以使用 `Array.push()`)。 然后,在查询数据库的方法的回调里通过 `save()` 方法更新 `Person` 的数据。
|
||||||
|
|
||||||
**Note:** This may be tricky, if in your Schema, you declared `favoriteFoods` as an Array, without specifying the type (i.e. `[String]`). In that case, `favoriteFoods` defaults to Mixed type, and you have to manually mark it as edited using `document.markModified('edited-field')`. See [Mongoose documentation](https://mongoosejs.com/docs/schematypes.html#Mixed)
|
**提示:** 如果你在 Schema 中将 `favoriteFoods` 声明为一个 Array(数组)并且没有指定数组的类型(如 `[String]`), 那么此时,`favoriteFoods` 就会是默认的 Mixed 类型。如果想编辑它,就必须执行 `document.markModified('edited-field')`。 详情请参阅 [Mongoose 文档](https://mongoosejs.com/docs/schematypes.html#Mixed)
|
||||||
|
|
||||||
# --hints--
|
# --hints--
|
||||||
|
|
||||||
Find-edit-update an item should succeed
|
应成功地对一条数据进行查找、编辑和更新
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) =>
|
(getUserInput) =>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: 587d7fb8367417b2b2512c0f
|
id: 587d7fb8367417b2b2512c0f
|
||||||
title: Perform New Updates on a Document Using model.findOneAndUpdate()
|
title: 在 document 中执行新的更新方式——使用 model.findOneAndUpdate()
|
||||||
challengeType: 2
|
challengeType: 2
|
||||||
forumTopicId: 301542
|
forumTopicId: 301542
|
||||||
dashedName: perform-new-updates-on-a-document-using-model-findoneandupdate
|
dashedName: perform-new-updates-on-a-document-using-model-findoneandupdate
|
||||||
@ -8,17 +8,17 @@ dashedName: perform-new-updates-on-a-document-using-model-findoneandupdate
|
|||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|
||||||
Recent versions of Mongoose have methods to simplify documents updating. Some more advanced features (i.e. pre/post hooks, validation) behave differently with this approach, so the classic method is still useful in many situations. `findByIdAndUpdate()` can be used when searching by id.
|
最近发布的 mongoose 版本简化了 document 的更新方式, 但同时,一些高级功能(如 pre/post hook, 验证)的使用方式也变得和以前不同。因此,在很多情景下,上一个挑战中提到的老方法其实更常用。 新方法的加入,可以让我们使用 `findByIdAndUpdate()` 来进行基于 id 的搜索。
|
||||||
|
|
||||||
# --instructions--
|
# --instructions--
|
||||||
|
|
||||||
Modify the `findAndUpdate` function to find a person by `Name` and set the person's age to `20`. Use the function parameter `personName` as the search key.
|
修改 `findAndUpdate` 函数,通过 `Name` 查询人,并将查到的人的年龄设为 `20` 岁, 将函数参数 `personName` 作为查询关键字。
|
||||||
|
|
||||||
**Note:** You should return the updated document. To do that, you need to pass the options document `{ new: true }` as the 3rd argument to `findOneAndUpdate()`. By default, these methods return the unmodified object.
|
**提示:** 你需要返回更新后的 document。 你可以把 `findOneAndUpdate()` 的第三个参数设置为 `{ new: true }` 。 默认情况下,这个方法会返回修改前的数据。
|
||||||
|
|
||||||
# --hints--
|
# --hints--
|
||||||
|
|
||||||
findOneAndUpdate an item should succeed
|
应成功地使用 findOneAndUpdate 更新数据
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) =>
|
(getUserInput) =>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: 587d7fb7367417b2b2512c0b
|
id: 587d7fb7367417b2b2512c0b
|
||||||
title: Use model.find() to Search Your Database
|
title: 使用 model.find() 查询数据库
|
||||||
challengeType: 2
|
challengeType: 2
|
||||||
forumTopicId: 301543
|
forumTopicId: 301543
|
||||||
dashedName: use-model-find-to-search-your-database
|
dashedName: use-model-find-to-search-your-database
|
||||||
@ -8,17 +8,17 @@ dashedName: use-model-find-to-search-your-database
|
|||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|
||||||
In its simplest usage, `Model.find()` accepts a query document (a JSON object) as the first argument, then a callback. It returns an array of matches. It supports an extremely wide range of search options. Read more in the docs.
|
我们尝试一种最简单的用法,`Model.find()` 接收一个查询 document(一个 JSON 对象)作为第一个参数,一个回调函数作为第二个参数, 它会返回由匹配到的数据组成的数组。 这个方法支持很多搜索选项, 详情请参阅文档。
|
||||||
|
|
||||||
# --instructions--
|
# --instructions--
|
||||||
|
|
||||||
Modify the `findPeopleByName` function to find all the people having a given name, using <code>Model.find() -\> [Person]</code>
|
修改 `findPeopleByName` 函数使用 <code>Model.find() -\> [Person]</code> 查询所有给定名字的人。
|
||||||
|
|
||||||
Use the function argument `personName` as the search key.
|
请使用函数参数中的 `personName` 作为搜索条件。
|
||||||
|
|
||||||
# --hints--
|
# --hints--
|
||||||
|
|
||||||
Find all items corresponding to a criteria should succeed
|
应成功地找到所有符合条件的数据
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) =>
|
(getUserInput) =>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: 587d7fb7367417b2b2512c0d
|
id: 587d7fb7367417b2b2512c0d
|
||||||
title: Use model.findById() to Search Your Database By _id
|
title: 使用 model.findById() 方法,根据 _id 来搜索数据
|
||||||
challengeType: 2
|
challengeType: 2
|
||||||
forumTopicId: 301544
|
forumTopicId: 301544
|
||||||
dashedName: use-model-findbyid-to-search-your-database-by-id
|
dashedName: use-model-findbyid-to-search-your-database-by-id
|
||||||
@ -8,15 +8,15 @@ dashedName: use-model-findbyid-to-search-your-database-by-id
|
|||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|
||||||
When saving a document, MongoDB automatically adds the field `_id`, and set it to a unique alphanumeric key. Searching by `_id` is an extremely frequent operation, so Mongoose provides a dedicated method for it.
|
在保存 document 的时候,MongoDB 会自动为它添加 `_id` 字段,并给该字段设置一个唯一的仅包含数字和字母的值。 通过 `_id` 搜索是一个十分常见的操作,为此,Mongoose 提供了一个专门的方法。
|
||||||
|
|
||||||
# --instructions--
|
# --instructions--
|
||||||
|
|
||||||
Modify the `findPersonById` to find the only person having a given `_id`, using `Model.findById() -> Person`. Use the function argument `personId` as the search key.
|
修改 `findPersonById`,用 `Model.findById() -> Person` 来查询唯一一个给定 `_id` 的人, 把函数参数 `personId` 作为查询键。
|
||||||
|
|
||||||
# --hints--
|
# --hints--
|
||||||
|
|
||||||
Find an item by Id should succeed
|
应成功地根据 Id 找到对应的数据
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) =>
|
(getUserInput) =>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: 587d7fb7367417b2b2512c0c
|
id: 587d7fb7367417b2b2512c0c
|
||||||
title: Use model.findOne() to Return a Single Matching Document from Your Database
|
title: 使用 model.findOne() 从数据库中返回一个单一匹配的 Document
|
||||||
challengeType: 2
|
challengeType: 2
|
||||||
forumTopicId: 301545
|
forumTopicId: 301545
|
||||||
dashedName: use-model-findone-to-return-a-single-matching-document-from-your-database
|
dashedName: use-model-findone-to-return-a-single-matching-document-from-your-database
|
||||||
@ -8,15 +8,15 @@ dashedName: use-model-findone-to-return-a-single-matching-document-from-your-dat
|
|||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|
||||||
`Model.findOne()` behaves like `Model.find()`, but it returns only one document (not an array), even if there are multiple items. It is especially useful when searching by properties that you have declared as unique.
|
`Model.findOne()` 与 `Model.find()` 十分类似,但就算数据库中有很多条数据可以匹配查询条件,它也只返回一个 document,而不会返回一个数组, 如果查询条件是声明为唯一值的属性,它会更加适用。
|
||||||
|
|
||||||
# --instructions--
|
# --instructions--
|
||||||
|
|
||||||
Modify the `findOneByFood` function to find just one person which has a certain food in the person's favorites, using `Model.findOne() -> Person`. Use the function argument `food` as search key.
|
修改 `findOneByFood` 函数,用 `Model.findOne() -> Person` 来查询在收藏夹中有某种食物的一个人。 将函数参数中的 `food` 作为检索条件。
|
||||||
|
|
||||||
# --hints--
|
# --hints--
|
||||||
|
|
||||||
Find one item should succeed
|
应成功地找到一个数据
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(getUserInput) =>
|
(getUserInput) =>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: 587d778b367417b2b2512aa8
|
id: 587d778b367417b2b2512aa8
|
||||||
title: Agregar un selector de fechas accesible
|
title: Agrega un selector de fechas accesible
|
||||||
challengeType: 0
|
challengeType: 0
|
||||||
videoUrl: 'https://scrimba.com/c/cR3bRbCV'
|
videoUrl: 'https://scrimba.com/c/cR3bRbCV'
|
||||||
forumTopicId: 301008
|
forumTopicId: 301008
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: 587d778f367417b2b2512aae
|
id: 587d778f367417b2b2512aae
|
||||||
title: Dar significado a los enlaces agregando un texto descriptivo
|
title: Da significado a los enlaces agregando un texto descriptivo
|
||||||
challengeType: 0
|
challengeType: 0
|
||||||
videoUrl: 'https://scrimba.com/c/c437DcV'
|
videoUrl: 'https://scrimba.com/c/c437DcV'
|
||||||
forumTopicId: 301013
|
forumTopicId: 301013
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: 587d778a367417b2b2512aa6
|
id: 587d778a367417b2b2512aa6
|
||||||
title: Mejorar la accesibilidad del campo de formulario con la etiqueta element
|
title: Mejora la accesibilidad del campo de formulario con el elemento label (etiqueta)
|
||||||
challengeType: 0
|
challengeType: 0
|
||||||
videoUrl: 'https://scrimba.com/c/cGJMMAN'
|
videoUrl: 'https://scrimba.com/c/cGJMMAN'
|
||||||
forumTopicId: 301016
|
forumTopicId: 301016
|
||||||
|
@ -15,7 +15,7 @@ Por defecto, un navegador representa estos elementos de manera similar a la humi
|
|||||||
|
|
||||||
El elemento `main` se usa para envolver (lo adivinaste) el contenido principal, y solo debe haber uno por página. Está destinado a rodear la información que está relacionada con el tema central de su página. No está destinado a incluir elementos que se repiten en todas las páginas, como enlaces de navegación o banners.
|
El elemento `main` se usa para envolver (lo adivinaste) el contenido principal, y solo debe haber uno por página. Está destinado a rodear la información que está relacionada con el tema central de su página. No está destinado a incluir elementos que se repiten en todas las páginas, como enlaces de navegación o banners.
|
||||||
|
|
||||||
La etiqueta `main` también tiene una característica de referencia insertada que la tecnología de asistencia puede usar para navegar rápidamente al contenido principal. Si alguna vez has visto un enlace "Salta al contenido principal" en la parte superior de una página, usando una etiqueta principal proporciona automáticamente a los dispositivos de asistencia esa funcionalidad.
|
La etiqueta `main` también tiene una característica de referencia insertada que la tecnología de asistencia puede usar para navegar rápidamente al contenido principal. Si alguna vez has visto un enlace de "saltar al contenido principal" en la parte superior de una página, el uso de una etiqueta `main` proporciona automáticamente esa funcionalidad a los dispositivos de asistencia.
|
||||||
|
|
||||||
# --instructions--
|
# --instructions--
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: 587d774c367417b2b2512a9d
|
id: 587d774c367417b2b2512a9d
|
||||||
title: Saber Cuando el Texto Alt Debe Dejarse en Blanco
|
title: Aprende cuando el texto alternativo debe dejarse en blanco
|
||||||
challengeType: 0
|
challengeType: 0
|
||||||
videoUrl: 'https://scrimba.com/c/cM9P4t2'
|
videoUrl: 'https://scrimba.com/c/cM9P4t2'
|
||||||
forumTopicId: 301019
|
forumTopicId: 301019
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: 587d7788367417b2b2512aa2
|
id: 587d7788367417b2b2512aa2
|
||||||
title: Haz que la navegación del lector de pantalla sea más fácil con el navegador Landmark
|
title: Haz que la navegación del lector de pantalla sea más fácil con el nav Landmark
|
||||||
challengeType: 0
|
challengeType: 0
|
||||||
videoUrl: 'https://scrimba.com/c/czVwWSv'
|
videoUrl: 'https://scrimba.com/c/czVwWSv'
|
||||||
forumTopicId: 301024
|
forumTopicId: 301024
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: 587d778c367417b2b2512aa9
|
id: 587d778c367417b2b2512aa9
|
||||||
title: Estandarizar horas con el atributo datetime HTML5
|
title: Estandariza horas con el atributo HTML5 datetime
|
||||||
challengeType: 0
|
challengeType: 0
|
||||||
videoUrl: 'https://scrimba.com/c/cmzMgtz'
|
videoUrl: 'https://scrimba.com/c/cmzMgtz'
|
||||||
forumTopicId: 301025
|
forumTopicId: 301025
|
||||||
@ -9,7 +9,7 @@ dashedName: standardize-times-with-the-html5-datetime-attribute
|
|||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|
||||||
Continuando con el tema de fecha, HTML5 también introdujo el elemento `time` junto con un atributo `datetime` para estandarizar los tiempos. Este es un elemento inline que puede ajustar una fecha u hora en una página. Un formato válido de esa fecha se mantiene mediante el atributo `datetime`. Este es el valor al que acceden los dispositivos de asistencia. Ayuda a evitar confusiones al indicar una versión estandarizada de un tiempo, incluso si está escrito de manera informal o coloquial en el texto.
|
Continuando con el tema de fechas, HTML5 también introdujo el elemento `time` junto con un atributo `datetime` para estandarizar las horas. Este es un elemento inline que puede ajustar una fecha u hora en una página. Un formato válido de esa fecha se mantiene mediante el atributo `datetime`. Este es el valor al que acceden los dispositivos de asistencia. Ayuda a evitar confusiones al indicar una versión estandarizada de una hora, incluso si está escrito de manera informal o coloquial en el texto.
|
||||||
|
|
||||||
Aquí hay un ejemplo:
|
Aquí hay un ejemplo:
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ dashedName: wrap-content-in-the-article-element
|
|||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|
||||||
`article` es otro de los nuevos elementos HTML5 que agrega significado semántico a tu lenguaje de marcado. `article` es un elemento de seccionamiento, y se utiliza para envolver contenido independiente y autónomo. La etiqueta funciona bien con entradas de blog, publicaciones en el foro o artículos de noticias.
|
`article` es otro de los nuevos elementos HTML5 que agrega significado semántico a tu lenguaje de marcado. `article` es un elemento de sección, y se utiliza para envolver contenido independiente y autónomo. La etiqueta funciona bien con entradas de blog, publicaciones en el foro o artículos de noticias.
|
||||||
|
|
||||||
Determinar si el contenido puede estar solo suele ser una decisión complicada, pero hay un par de pruebas simples que puedes usar. Pregúntate, si elimino todo el contexto circundante, ¿ese contenido aún tendría sentido? Del mismo modo para el texto, ¿el contenido se mantendría si estuviera en una fuente RSS?
|
Determinar si el contenido puede estar solo suele ser una decisión complicada, pero hay un par de pruebas simples que puedes usar. Pregúntate, si elimino todo el contexto circundante, ¿ese contenido aún tendría sentido? Del mismo modo para el texto, ¿el contenido se mantendría si estuviera en una fuente RSS?
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: 587d781b367417b2b2512abc
|
id: 587d781b367417b2b2512abc
|
||||||
title: Ajusta la propiedad de background-color del texto
|
title: Ajusta la propiedad background-color del texto
|
||||||
challengeType: 0
|
challengeType: 0
|
||||||
videoUrl: 'https://scrimba.com/c/cEDqwA6'
|
videoUrl: 'https://scrimba.com/c/cEDqwA6'
|
||||||
forumTopicId: 301032
|
forumTopicId: 301032
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: 587d7791367417b2b2512ab5
|
id: 587d7791367417b2b2512ab5
|
||||||
title: Ajustar la altura de un elemento con la propiedad height
|
title: Ajusta la altura de un elemento utilizando la propiedad height
|
||||||
challengeType: 0
|
challengeType: 0
|
||||||
videoUrl: 'https://scrimba.com/c/cEDaDTN'
|
videoUrl: 'https://scrimba.com/c/cEDaDTN'
|
||||||
forumTopicId: 301034
|
forumTopicId: 301034
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: 587d781d367417b2b2512ac8
|
id: 587d781d367417b2b2512ac8
|
||||||
title: Ajustar el hover de una etiqueta ancla
|
title: Ajusta el hover de una etiqueta anchor
|
||||||
challengeType: 0
|
challengeType: 0
|
||||||
videoUrl: 'https://scrimba.com/c/cakRGcm'
|
videoUrl: 'https://scrimba.com/c/cakRGcm'
|
||||||
forumTopicId: 301035
|
forumTopicId: 301035
|
||||||
@ -9,9 +9,9 @@ dashedName: adjust-the-hover-state-of-an-anchor-tag
|
|||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|
||||||
En este desafío, se incluye el uso de pseudo-clases. Una pseudo-clase es una palabra clave que se puede agregar a los selectores para seleccionar un estado específico de un elemento.
|
Este desafío mostrará el uso de las pseudo-clases. Una pseudo-clase es una palabra clave que se puede agregar a los selectores para seleccionar un estado específico de un elemento.
|
||||||
|
|
||||||
Por ejemplo, el estilo de una etiqueta "anchor" puede ser cambiado para su estado hover usando el selector de pseudo-clase `:hover`. Aquí está el CSS para cambiar el color `color` de la etiqueta de "anchor" a rojo durante el estado hover:
|
Por ejemplo, el estilo de una etiqueta "anchor" puede ser cambiado por el estado de su hover utilizando el selector de pseudo-clase `:hover`. Aquí está el CSS para cambiar el color `color` de la etiqueta de "anchor" a rojo durante el estado hover:
|
||||||
|
|
||||||
```css
|
```css
|
||||||
a:hover {
|
a:hover {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: 587d78a4367417b2b2512ad4
|
id: 587d78a4367417b2b2512ad4
|
||||||
title: Ajustar el tono de un color
|
title: Ajusta el matiz de un color
|
||||||
challengeType: 0
|
challengeType: 0
|
||||||
videoUrl: 'https://scrimba.com/c/cPp38TZ'
|
videoUrl: 'https://scrimba.com/c/cPp38TZ'
|
||||||
forumTopicId: 301036
|
forumTopicId: 301036
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: 587d781b367417b2b2512abd
|
id: 587d781b367417b2b2512abd
|
||||||
title: Ajustar el tamaño de un encabezado contra una etiqueta de párrafo
|
title: Ajusta el tamaño de un título contra una etiqueta de párrafo
|
||||||
challengeType: 0
|
challengeType: 0
|
||||||
videoUrl: 'https://scrimba.com/c/c3bRPTz'
|
videoUrl: 'https://scrimba.com/c/c3bRPTz'
|
||||||
forumTopicId: 301037
|
forumTopicId: 301037
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: 587d78a4367417b2b2512ad5
|
id: 587d78a4367417b2b2512ad5
|
||||||
title: Ajustar el tono de un color
|
title: Ajusta el tono de un color
|
||||||
challengeType: 0
|
challengeType: 0
|
||||||
videoUrl: 'https://scrimba.com/c/cEDJvT7'
|
videoUrl: 'https://scrimba.com/c/cEDJvT7'
|
||||||
forumTopicId: 301038
|
forumTopicId: 301038
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: 587d7791367417b2b2512ab4
|
id: 587d7791367417b2b2512ab4
|
||||||
title: Ajustar el ancho de un elemento utilizando la propiedad width
|
title: Ajusta el ancho de un elemento utilizando la propiedad width
|
||||||
challengeType: 0
|
challengeType: 0
|
||||||
videoUrl: 'https://scrimba.com/c/cvVLPtN'
|
videoUrl: 'https://scrimba.com/c/cvVLPtN'
|
||||||
forumTopicId: 301039
|
forumTopicId: 301039
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: 587d7791367417b2b2512ab3
|
id: 587d7791367417b2b2512ab3
|
||||||
title: Crea balance visual usando la propiedad text-align
|
title: Crea un balance visual usando la propiedad text-align
|
||||||
challengeType: 0
|
challengeType: 0
|
||||||
videoUrl: 'https://scrimba.com/c/c3b4EAp'
|
videoUrl: 'https://scrimba.com/c/c3b4EAp'
|
||||||
forumTopicId: 301053
|
forumTopicId: 301053
|
||||||
@ -9,7 +9,7 @@ dashedName: create-visual-balance-using-the-text-align-property
|
|||||||
|
|
||||||
# --description--
|
# --description--
|
||||||
|
|
||||||
Esta sección del currículo se enfoca en Diseño Visual Aplicado. El primer grupo de desafíos están construidos sobre el diseño de la tarjeta dada para mostrar un número de principios fundamentales.
|
Esta sección del currículo se enfoca en el Diseño Visual Aplicado. El primer grupo de desafíos se basa en el diseño de la tarjeta provista para mostrar un número de principios fundamentales.
|
||||||
|
|
||||||
El texto es frecuentemente una gran parte del contenido web. CSS tiene múltiples opciones para alinearlo con la propiedad `text-align`.
|
El texto es frecuentemente una gran parte del contenido web. CSS tiene múltiples opciones para alinearlo con la propiedad `text-align`.
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: 587d781e367417b2b2512acb
|
id: 587d781e367417b2b2512acb
|
||||||
title: Bloquea un elemento a su padre con posicionamiento absoluto
|
title: Bloquea un elemento con relación a su padre con el posicionamiento absoluto
|
||||||
challengeType: 0
|
challengeType: 0
|
||||||
videoUrl: 'https://scrimba.com/c/cyLJ7c3'
|
videoUrl: 'https://scrimba.com/c/cyLJ7c3'
|
||||||
forumTopicId: 301060
|
forumTopicId: 301060
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: 587d781e367417b2b2512acc
|
id: 587d781e367417b2b2512acc
|
||||||
title: Bloquear un elemento en la ventana del explorador con posicionamiento fijo (fixed)
|
title: Bloquea un elemento a la ventana del navegador con el posicionamiento fijo
|
||||||
challengeType: 0
|
challengeType: 0
|
||||||
videoUrl: 'https://scrimba.com/c/c2MDNUR'
|
videoUrl: 'https://scrimba.com/c/c2MDNUR'
|
||||||
forumTopicId: 301061
|
forumTopicId: 301061
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: 587d781a367417b2b2512ab7
|
id: 587d781a367417b2b2512ab7
|
||||||
title: Usa la etiqueta fuerte para hacer que el texto sea negrita
|
title: Utiliza la etiqueta strong para poner el texto en negrita
|
||||||
challengeType: 0
|
challengeType: 0
|
||||||
videoUrl: 'https://scrimba.com/c/ceJNBSb'
|
videoUrl: 'https://scrimba.com/c/ceJNBSb'
|
||||||
forumTopicId: 301080
|
forumTopicId: 301080
|
||||||
@ -29,7 +29,7 @@ La etiqueta `strong` debe estar dentro de la etiqueta `p`.
|
|||||||
assert($('p').children('strong').length == 1);
|
assert($('p').children('strong').length == 1);
|
||||||
```
|
```
|
||||||
|
|
||||||
The `strong` tag should wrap around the words `Stanford University`.
|
La etiqueta `strong` debe envolver el texto `Stanford University`.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
assert(
|
assert(
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: 587d781c367417b2b2512ac0
|
id: 587d781c367417b2b2512ac0
|
||||||
title: Usar la propiedad de text-transform para hacer texto mayúscula
|
title: Usa la propiedad text-transform para hacer el texto mayúsculas
|
||||||
challengeType: 0
|
challengeType: 0
|
||||||
videoUrl: 'https://scrimba.com/c/cvVZQSP'
|
videoUrl: 'https://scrimba.com/c/cvVZQSP'
|
||||||
forumTopicId: 301081
|
forumTopicId: 301081
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: bad87fee1348bd8aedf06756
|
id: bad87fee1348bd8aedf06756
|
||||||
title: Sobreescribe las declaraciones de clase dando estilo a atributos ID
|
title: Sobreescribe declaraciones de clase dando estilo a atributos ID
|
||||||
challengeType: 0
|
challengeType: 0
|
||||||
videoUrl: 'https://scrimba.com/c/cRkpDhB'
|
videoUrl: 'https://scrimba.com/c/cRkpDhB'
|
||||||
forumTopicId: 18251
|
forumTopicId: 18251
|
||||||
@ -31,7 +31,7 @@ Crea una declaración CSS para el id `orange-text` en el elemento `style`. Aquí
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
**Nota:** No importa si declaras el CSS arriba o debajo de la clase pink-text, ya que el atributo id siempre tendrá precedencia.
|
**Nota:** No importa si declaras este CSS arriba o debajo de la clase `pink-text`, ya que el atributo `id` siempre tendrá precedencia.
|
||||||
|
|
||||||
# --hints--
|
# --hints--
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: bad87fee1348bd9aedf08726
|
id: bad87fee1348bd9aedf08726
|
||||||
title: Utiliza código hexadecima (hex code) para indicar colores específicos
|
title: Utiliza código hexadecimal (hex code) para indicar colores específicos
|
||||||
challengeType: 0
|
challengeType: 0
|
||||||
videoUrl: 'https://scrimba.com/c/c8W9mHM'
|
videoUrl: 'https://scrimba.com/c/c8W9mHM'
|
||||||
forumTopicId: 18350
|
forumTopicId: 18350
|
||||||
|
@ -19,12 +19,12 @@ El `!` y `DOCTYPE` en mayúsculas es importante, especialmente para los navegado
|
|||||||
|
|
||||||
A continuación, el resto de tu código HTML necesita ser envuelto en etiquetas `html`. La apertura `<html>` va directamente debajo de la línea `<!DOCTYPE html>`, y el cierre `</html>` va en el final de la página.
|
A continuación, el resto de tu código HTML necesita ser envuelto en etiquetas `html`. La apertura `<html>` va directamente debajo de la línea `<!DOCTYPE html>`, y el cierre `</html>` va en el final de la página.
|
||||||
|
|
||||||
Aquí hay un ejemplo de estructura de página:
|
Aquí hay un ejemplo de estructura de página. Tu código HTML iría en el espacio entre las dos etiquetas `html`.
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<!-- Your HTML code goes here -->
|
|
||||||
</html>
|
</html>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -19,10 +19,11 @@ Aquí hay un ejemplo de la disposición de una página:
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<!-- metadata elements -->
|
<meta />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<!-- page contents -->
|
<div>
|
||||||
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
```
|
```
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: bad87fee1348bd9aedf08816
|
id: bad87fee1348bd9aedf08816
|
||||||
title: Enlaza hacia páginas externas con los elementos "anchor"
|
title: Enlaza hacia páginas externas con los elementos anchor
|
||||||
challengeType: 0
|
challengeType: 0
|
||||||
videoUrl: 'https://scrimba.com/p/pVMPUv/c8EkncB'
|
videoUrl: 'https://scrimba.com/p/pVMPUv/c8EkncB'
|
||||||
forumTopicId: 18226
|
forumTopicId: 18226
|
||||||
|
@ -17,11 +17,23 @@ Puedes anidar enlaces dentro de otros elementos de texto.
|
|||||||
</p>
|
</p>
|
||||||
```
|
```
|
||||||
|
|
||||||
Vamos a desglosar el ejemplo: El texto regular está envuelto en el elemento `p`:
|
Desglosemos el ejemplo. El texto normal está envuelto en el elemento `p`:
|
||||||
`<p> Here's a ... for you to follow. </p>` Le sigue el elemento *anchor* `<a>` (el cual requiere una etiqueta de cierre `</a>`):
|
|
||||||
`<a> ... </a>`. `target` es un atributo de la etiqueta anchor que especifica donde abrir el enlace y el valor `_blank` especifica abrir el enlace en una nueva pestaña, `href` es un atributo de la etiqueta anchor que contiene la dirección URL del enlace:
|
`<p> Here's a ... for you to follow. </p>`
|
||||||
`<a href="http://freecodecamp.org"> ... </a>`. El texto, **"link to freecodecamp.org"**, dentro del elemento `a` llamado `anchor text`, mostrará un enlace para hacer click:
|
|
||||||
`<a href=" ... ">link to freecodecamp.org</a>`. El resultado final del ejemplo se verá así:
|
A continuación está el elemento *anchor* `<a>` (que requiere una etiqueta de cierre `</a>`):
|
||||||
|
|
||||||
|
`<a> ... </a>`
|
||||||
|
|
||||||
|
`target` es un atributo de etiqueta anchor que especifica dónde abrir el enlace. El valor `_blank` especifica abrir el enlace en una nueva pestaña. El `href` es un atributo de etiqueta anchor que contiene la dirección URL del enlace:
|
||||||
|
|
||||||
|
`<a href="http://freecodecamp.org"> ... </a>`
|
||||||
|
|
||||||
|
El texto, `link to freecodecamp.org`, dentro de un elemento `a` se llama `anchor text`, y mostrará el enlace para hacer clic:
|
||||||
|
|
||||||
|
`<a href=" ... ">link to freecodecamp.org</a>`
|
||||||
|
|
||||||
|
El resultado final del ejemplo se verá así:
|
||||||
|
|
||||||
Aquí hay un enlace [a freecodecamp.org](http://freecodecamp.org) para que lo sigas.
|
Aquí hay un enlace [a freecodecamp.org](http://freecodecamp.org) para que lo sigas.
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ dashedName: say-hello-to-html-elements
|
|||||||
|
|
||||||
Bienvenido a los desafíos de programación HTML de freeCodeCamp. Estos te guiarán paso a paso a través del mundo del desarrollo web.
|
Bienvenido a los desafíos de programación HTML de freeCodeCamp. Estos te guiarán paso a paso a través del mundo del desarrollo web.
|
||||||
|
|
||||||
Primero, comenzarás construyendo una página web simple usando HTML. Puedes editar el código desde tu editor de código, el cual está incrustado en esta página web.
|
Primero, comenzarás construyendo una página web simple usando HTML. Puedes editar el código desde tu editor de código, el cual está insertado en esta página web.
|
||||||
|
|
||||||
¿Ves el código en tu editor de código que dice `<h1>Hello</h1>`? Ese es un elemento HTML.
|
¿Ves el código en tu editor de código que dice `<h1>Hello</h1>`? Ese es un elemento HTML.
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ Sin embargo, usar la propiedad `flex-wrap` le indica al CSS que envuelva los ele
|
|||||||
|
|
||||||
CSS también tiene opciones para la dirección de la envoltura:
|
CSS también tiene opciones para la dirección de la envoltura:
|
||||||
|
|
||||||
<ul><li><code>nowrap</code>: esta es la configuración predeterminada, y no envuelve elementos.</li><li><code>wrap</code>: envuelve elementos de izquierda a derecha si están en una fila, o de arriba hacia abajo si están en una columna.</li><li><code>wrap-reverse</code>: envuelve elementos de derecha a izquierda si están en una fila, o de abajo hacia arriba si están en una columna.</li></ul>
|
<ul><li><code>nowrap</code>: esta es la configuración predeterminada, y no envuelve elementos.</li><li><code>wrap</code>: envuelve elementos en múltiples líneas de arriba a abajo si están en filas y de izquierda a derecha si están en columnas.</li><li><code>wrap-reverse</code>: envuelve elementos en múltiples líneas de abajo hacia arriba si están en filas y de derecha a izquierda si están en columnas.</li></ul>
|
||||||
|
|
||||||
# --instructions--
|
# --instructions--
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ Convierte cualquier elemento HTML en una grid al establecer la propiedad `displa
|
|||||||
|
|
||||||
# --instructions--
|
# --instructions--
|
||||||
|
|
||||||
Cambia la visualización del div que tiene la clase `container` a `grid`.
|
Cambia la propiedad display del div que tiene la clase `container` a `grid`.
|
||||||
|
|
||||||
# --hints--
|
# --hints--
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ Las líneas horizontales y verticales hipotéticas que crean la cuadrícula son
|
|||||||
|
|
||||||
Así es como se ven las líneas para una grid de 3x3:
|
Así es como se ven las líneas para una grid de 3x3:
|
||||||
|
|
||||||
<div style='position:relative;margin:auto;background:Gainsboro;display:block;margin-top:100px;margin-bottom:50px;width:200px;height:200px;'><p style='left:25%;top:-30%;font-size:130%;position:absolute;color:RoyalBlue;'>líneas de columna</p><p style='left:0%;top:-15%;font-size:130%;position:absolute;color:RoyalBlue;'>1</p><p style='left:30%;top:-15%;font-size:130%;position:absolute;color:RoyalBlue;'>2</p><p style='left:63%;top:-15%;font-size:130%;position:absolute;color:RoyalBlue;'>3</p><p style='left:95%;top:-15%;font-size:130%;position:absolute;color:RoyalBlue;'>4</p><p style='left:-40%;top:45%;font-size:130%;transform:rotateZ(-90deg);position:absolute;'>5</p><p style='left:-10%;top:-10%;font-size:130%;position:absolute;'>1</p><p style='left:-10%;top:21%;font-size:130%;position:absolute;'>2</p><p style='left:-10%;top:53%;font-size:130%;position:absolute;'>3</p><p style='left:-10%;top:85%;font-size:130%;position:absolute;'>4</p><div style='left:0%;top:0%;width:5%;height:100%;background:RoyalBlue;position:absolute;'></div><div style='left:31%;top:0%;width:5%;height:100%;background:RoyalBlue;position:absolute;'></div><div style='left:63%;top:0%;width:5%;height:100%;background:RoyalBlue;position:absolute;'></div><div style='left:95%;top:0%;width:5%;height:100%;background:RoyalBlue;position:absolute;'></div><div style='left:0%;top:0%;width:100%;height:5%;background:black;position:absolute;'></div><div style='left:0%;top:31%;width:100%;height:5%;background:black;position:absolute;'></div><div style='left:0%;top:63%;width:100%;height:5%;background:black;position:absolute;'></div><div style='left:0%;top:95%;width:100%;height:5%;background:black;position:absolute;'></div></div>
|
<div style='position:relative;margin:auto;background:Gainsboro;display:block;margin-top:100px;margin-bottom:50px;width:200px;height:200px;'><p style='left:25%;top:-30%;font-size:130%;position:absolute;color:RoyalBlue;'>columnas</p><p style='left:0%;top:-15%;font-size:130%;position:absolute;color:RoyalBlue;'>1</p><p style='left:30%;top:-15%;font-size:130%;position:absolute;color:RoyalBlue;'>2</p><p style='left:63%;top:-15%;font-size:130%;position:absolute;color:RoyalBlue;'>3</p><p style='left:95%;top:-15%;font-size:130%;position:absolute;color:RoyalBlue;'>4</p><p style='left:-40%;top:45%;font-size:130%;transform:rotateZ(-90deg);position:absolute;'>filas</p><p style='left:-10%;top:-10%;font-size:130%;position:absolute;'>1</p><p style='left:-10%;top:21%;font-size:130%;position:absolute;'>2</p><p style='left:-10%;top:53%;font-size:130%;position:absolute;'>3</p><p style='left:-10%;top:85%;font-size:130%;position:absolute;'>4</p><div style='left:0%;top:0%;width:5%;height:100%;background:RoyalBlue;position:absolute;'></div><div style='left:31%;top:0%;width:5%;height:100%;background:RoyalBlue;position:absolute;'></div><div style='left:63%;top:0%;width:5%;height:100%;background:RoyalBlue;position:absolute;'></div><div style='left:95%;top:0%;width:5%;height:100%;background:RoyalBlue;position:absolute;'></div><div style='left:0%;top:0%;width:100%;height:5%;background:black;position:absolute;'></div><div style='left:0%;top:31%;width:100%;height:5%;background:black;position:absolute;'></div><div style='left:0%;top:63%;width:100%;height:5%;background:black;position:absolute;'></div><div style='left:0%;top:95%;width:100%;height:5%;background:black;position:absolute;'></div></div>
|
||||||
|
|
||||||
Para controlar la cantidad de columnas que un elemento tendrá, puedes usar la propiedad `grid-column` en conjunto con el número de las líneas en las que quieres que empiece y termine.
|
Para controlar la cantidad de columnas que un elemento tendrá, puedes usar la propiedad `grid-column` en conjunto con el número de las líneas en las que quieres que empiece y termine.
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user