我也知道有很多工具可以快速搭建 react,甚至只需要写业务代码,但是遇到底层(其实这也不算底层)的东西,或者需要高度自定义的东西的时候,那些脚手架显然是不够用的。
npx create-react-app part1
在 part1 文件夹中使用官方脚手架创建一个基础的 react 项目。有一点需要注意,npx
执行产生的 lock文件
是 npm
的 lock文件
,如果需要用到 yarn
,则使用 yarn create react-app part1
。
ReactDOM.render(<App />, document.getElementById('root'))
这是将其内容渲染到 div 元素中,其 id 值为 ‘root’,该元素在文件 public/index.html 中定义。
关于babel,在使用 create-React-app 创建的 React 应用中转译是自动配置好的。
与其他语言相反,在 JavaScript 中,this 的值是根据 方法如何调用 来定义的。 当通过引用调用该方法时, this 的值就变成了所谓的全局对象。
通常在 JSX-模板 中定义事件处理程序并不是一个好的实践。 无论如何,让我们将事件处理程序分离成单独的函数。
部件并不会重新渲染。 我们可以通过再次调用 ReactDOM.render 方法让组件重新渲染,当然我们现在有 useState 不需要这样子,而且这样也十分耗性能。
1 | let counter = 1; |
实际上, { …clicks } 创建了一个新对象,该对象是具有 clicks 对象的所有属性的副本。 当我们向对象添加新属性时,例如 { …clicks, right: 1 },新对象中 right 属性的值将为 1。
【Hook 的规则】 不能从循环、条件表达式或任何不是定义组件的函数的地方调用 useState (同样的还有 useEffect 函数,将在后面的课程中介绍)。 这样做是为了确保 Hook 总是以相同的顺序调用,如果不是这样,应用的行为就会不规则。
onClick 与 setTimeout 一样,接收的是一个函数(事件处理程序)而不是一个函数执行(function call)。
我们的事件处理被定义为 function call,这意味着事件处理程序实际上被分配了函数返回的值,而 console.log 的返回值是 undefined。
当然如果函数的返回值是函数的话,即使接收函数执行也没关系。
1 | // 可正常执行 |
Do Not Define Components Within Components 【不要在组件中定义组件】
列表项,即 map 方法生成的每个元素,都必须有一个唯一的键值: 一个名为 key 的属性。
json-server
您可以使用命令 npm install -g json-server
在您的机器上安装 JSON 服务器。
1 | npx json-server --port 3001 --watch db.json |
REST
在 REST 术语中,我们将单个数据对象(如应用中的便笺)称为 resources。 每个资源都有一个唯一的地址——它的 URL。 根据 json-server 使用的一般约定,我们将能够在资源 URL, 即 notes/3 上定位某个便笺,其中 3 是资源的 id。 另一方面, notes url 指向包含所有便笺的资源集合。
通过 HTTP GET 请求从服务器获取资源。 例如,对 URLnotes/3 的 HTTP GET 请求将返回 id 为 3 的便笺。 对 notes URL 的 HTTP GET 请求将返回所有便笺的列表。
根据 json 服务器遵守的 REST 约定,通过向 notes URL 发出 HTTP POST 请求来创建、存储新的便笺。 新便笺资源的数据在请求的 body 中发送。
Json-server 要求以 JSON 格式发送所有数据。 实际上,这意味着数据必须是格式正确的字符串,并且请求必须包含值为 application/json 的 Content-Type 请求头。
nodemon
如果我们对应用的代码进行更改,我们必须重新启动应用以查看更改。 我们通过键入 ⌃+C 首先关闭应用,然后重新启动应用。 与 React 中方便的工作流程相比,Node 就有点麻烦,在 React 中,浏览器会在进行更改后自动重新加载。
解决这个问题的方法是使用 nodemon :
nodemon 将监视启动 nodemon 的目录中的文件,如果任何文件发生更改,nodemon 将自动重启 node 应用。
cors
请记住,同源策略和 CORS 并不是特定于 React 或 Node 的。 它们实际上是 web 应用操作的通用原则。
我们可以通过使用 Node 的 cors 中间件来允许来自其他源的请求。
eslint 配置
npm install eslint –save-dev
npx eslint –init
许多公司定义了通过 ESlint 配置文件在整个组织中执行的编码标准。 建议不要一遍又一遍地使用重造轮子,从别人的项目中采用现成的配置到自己的项目中可能是一个好主意。 最近,很多项目都采用了 Airbnb 的 Javascript 风格指南,使用了 Airbnb 的 ESlint 。
mongo
pwd: lsy…
为什么要用 TypeScript?
在不同的论坛上,你可能会遇到很多支持或反对 TypeScript 的争论。 事实很可能是模糊的: 这取决于你的需求和对 TypeScript 所提供函数的使用。 但无论如何,这里解释了我们为什么认为使用 TypeScript 有一些优势,以及这背后的一些原因。
首先,TypeScript 提供了类型检查和静态代码分析。 我们可以要求值具有某种类型,并让编译器警告不要使用错误的值。 这可以减少运行时错误,甚至可以减少项目中所需的单元测试数量,至少在涉及纯类型测试时是这样。
静态程序分析不仅警告错误的类型使用,还有其他错误,比如拼错变量或函数名,或者试图使用超出范围的变量。
TypeScript 的第二个优点是代码中的类型注解可以作为代码级文档 的类型发挥作用。
通过函数签名可以很容易地检查函数可以使用哪种类型的参数,以及它将返回哪种类型的数据。 这种类型的类型注解绑定文档将始终是最新的,并且它使新的程序员更容易开始处理现有的项目。 当返回到一个旧的项目时,这也是有帮助的。
类型可以在整个代码库中重用,对类型定义的更改将自动反映所有使用该类型的地方。 有人可能会说,你可以用 JSDoc 实现类似的代码级文档,但是它与代码的连接不像 TypeScript 的类型那样紧密,因此更有可能不同步,而且也更加冗长。
TypeScript 的第三个优点是,当 IDE 确切知道您正在处理的数据类型时,它们可以提供更具体、更智能的智能感知。
当您需要重构代码时,所有这些特性都非常有用。 静态程序分析会警告你代码中的任何错误,智能感知可以提示你可用的属性,甚至可能的重构选项。 代码级文档可以帮助您理解现有的代码。
在 TypeScript 的帮助下,在早期阶段仅仅通过改变配置就可以很容易地开始使用最新的 JavaScript 语言特性。
TypeScript 不能解决什么问题?
如上所述,TypeScript 类型注解和类型检查仅在编译时存在,在运行时不再存在。 即使编译器没有抛出任何错误,运行时仍然是有可能抛出错误的。
这些运行时错误在处理外部输入(如从网络请求接收的数据)时特别常见。
最后,下面我们列举了一些 TypeScript 中存在的问题,这些问题值得注意:
Incomplete, invalid or missing types in external libraries【外部库中不完整、无效或缺少的类型】
在使用外部库时,您可能会发现某些库缺少或以某种方式存在无效的类型声明。 大多数情况下,这是因为库不是用 TypeScript 编写的,而且手动添加类型声明的人并没有很好地处理它。 在这些情况下,您可能需要自己定义类型声明。
但是,很有可能已经有人为您正在使用的包添加了类型。 因此总是先检查 DefinitelyTyped 或他们的 GitHub 页面。 它们可能是最常用的类型声明文件源。
否则,你可能需要从熟悉 TypeScript 自己关于类型声明的文档开始。
Sometimes type inference needs assistance【有时候类型推断需要帮助】
TypeScript 中的类型推断非常好,但还不够完美。
有时候你可能觉得你已经完美的声明了你的类型,但是编译器仍然告诉你这个属性不存在或者这种用法是不允许的。 在这些情况下,您可能需要通过类似“外挂”类型检查来帮助编译器,但是要小心类型强制转换和类型保护。
使用类型强制转换或类型保护,基本上就是向编译器说明值确实是您声明的类型。
你可能想看看 TypeScript 关于 Type Assertions 和 Type Guards 的文档。
Mysterious type errors【神秘的类型错误】
类型系统给出的错误有时可能很难理解,特别是当您使用复杂类型时。
按照经验法则,TypeScript 错误消息在消息末尾具有最有用的信息。
当你遇到长长的令人困惑的信息时,从最后开始阅读。
@types/{npm_package}
通常,现有包的类型可以在 npm 中的 @types-organization 中找到,您可以通过安装一个名为@types /-prefix 的 npm 包将相关类型添加到项目中。 例如: npm install –save-dev @types/react @types/express @types/lodash @types/jest @types/mongoose 等等。 @types/* 由 Definitely typed 维护,这是一个社区项目,其目标是将所有的类型维护在一个地方。
基本的 TSConfig
根据你要在其中运行代码的不同的 JavaScript 运行时环境,你可以在 github.com/tsconfig/bases 上寻找一个合适的基本配置。 你可以通过扩展这些已经处理过不同的 JavaScript 运行时环境的 tsconfig.json 文件来简化你项目中的 tsconfig.json。
举个例子,如果你的项目是基于 Node.js 12.x 写的,那么你可以使用 npm 模块:@tsconfig/node12:
1 | { |
eslint
如果我们想要阻止开发人员使用 any 类型,该怎么办? 幸运的是,除了 tsconfig.json 之外,我们还有其他方法来强制执行编码样式。 我们能做的就是用 eslint 来管理我们的代码。
让我们安装 eslint 和它的 TypeScript 扩展:
npm install –save-dev eslint @typescript-eslint/eslint-plugin @typescript-eslint/parser
我们将 eslint 配置为 disallow explicit any, 将如下规则写入 .eslintrc:
1 | { |
在推荐的设置之上,我们应该尝试熟悉这一章节所需的编码风格,并将每行代码末尾的分号设置为 required。
所以我们将使用下面的 .eslintrc
1 | { |
https://fullstackopen.com/zh/part9/%E7%89%88%E7%9A%84express%E5%BA%94%E7%94%A8
除非没有其他方法,否则我们永远不应该使用类型断言,因为我们总是有可能断言对象的类型不合适,从而导致严重的运行时错误。
1 | npx eslint --init |
ts react
依旧是 npx create-react-app 但是加了一些参数,让它创建(下载)的模板使用的是 typescript
1 | npx create-react-app my-app --template typescript |
如果你浏览这些文件和文件夹,你会发现这个应用和你用纯 JavaScript 初始化的应用没什么不同。 基本上,唯一的区别是 .js 和我.jsx 文件现在改名为 .ts 和 .tsx 文件,它们包含一些类型注解,根文件夹还包含一个 tsconfig.json 文件。
让我们看看为我们创建的 tsconfig.json 文件。 文件中的所有内容都应该差不多正常,只是目前的配置还允许编译 JavaScript 文件,因为 allowJs 被设置为 true。 如果你需要混合使用 TypeScript 和 JavaScript (例如,如果你正在将一个 JavaScript 项目转换成 TypeScript 或者其他原因) ,那么这样做是可以的,但是我们希望我们的应用是纯粹的 TypeScript,所以让我们把这个设置改为 false。