diff --git a/README-en.md b/README-en.md index 305770b..1812e8f 100755 --- a/README-en.md +++ b/README-en.md @@ -2,6 +2,12 @@ > Click :star:if you like the project. Pull Request are highly appreciated. +<<前端进阶篇 v1.1>> PDF 出炉了 — 「阿宝哥」,精心准备的 9 万多字 242 页的前端进阶资料。发布后 5 天内下载量为 **3170**。 + + + +点击此 [全栈修仙之路 - 前端进阶篇](http://book.bugstack.cn/#s/6I-ldR3A) 链接,即可免费下载电子书。 + ### Table of Contents | No. | Questions | @@ -315,16 +321,15 @@ |299| [How to add a bootstrap for a react application?](#how-to-add-a-bootstrap-for-a-react-application)| |300| [Can you list down top websites or applications using react as front end framework?](#can-you-list-down-top-websites-or-applications-using-react-as-front-end-framework)| |301| [Is it recommended to use CSS In JS technique in React?](#is-it-recommended-to-use-css-in-js-technique-in-react)| +|302| [Do I need to rewrite all my class components with hooks?](#do-i-need-to-rewrite-all-my-class-components-with-hooks)| +|303| [How to fetch data with React Hooks?](#how-to-fetch-data-with-react-hooks)| +|304| [Is Hooks cover all use cases for classes?](#is-hooks-cover-all-use-cases-for-classes)| ## Core React 1. ### What is React? React is an **open-source frontend JavaScript library** which is used for building user interfaces especially for single page applications. It is used for handling view layer for web and mobile apps. React was created by Jordan Walke, a software engineer working for Facebook. React was first deployed on Facebook's News Feed in 2011 and on Instagram in 2012. - - React 是一个开源的前端 JavaScript 框架,可用于构建用户界面特别是单页应用程序。它被用于作为网页和移动应用的视图层。React 由 Facebook - 的工程师 Jordan Walke 创建。在 2011 年 React 应用首次被部署到 Facebook 的信息流上,之后于 2012 年被应用到 Instagram 中。 - 2. ### What are the major features of React? @@ -335,12 +340,6 @@ * Follows *Unidirectional** data flow or data binding. * Uses **reusable/composable** UI components to develop the view. - React 的主要特性有: - * 考虑到真实的 DOM 操作比较昂贵,它使用 VirtualDOM 来替代真实的 DOM - * 支持服务端渲染 - * 遵从单向数据流或数据绑定 - * 使用可重用/可组合的 UI 组件开发视图 - 3. ### What is JSX? *JSX* is a XML-like syntax extension to ECMAScript (the acronym stands for *JavaScript XML*). Basically it just provides syntactic sugar for the `React.createElement()` function, giving us expressiveness of JavaScript along with HTML like template syntax. @@ -358,31 +357,11 @@ } } ``` - JSX 是一个对 ECMAScript 进行类 XML 的语法的扩展。它只是为 `React.createElement()` 函数提供语法糖,从而让在我们在 JavaScript 中, - 使用类 HTML 模板的语法,进行页面描述。 - - 在以下示例中,在 `

` 标签中的文本会以 JavaScript 函数的形式返回给渲染函数。 - - ```jsx harmony - class App extends React.Component { - render() { - return( -
-

{'Welcome to React world!'}

-
- ) - } - } - ``` - 4. ### What is the difference between Element and Component? An *Element* is a plain object describing what you want to appear on the screen in terms of the DOM nodes or other components. *Elements* can contain other *Elements* in their props. Creating a React element is cheap. Once an element is created, it is never mutated. - 一个 Element 是一个普通的对象,以 DOM 节点或其他组件的方式描述你期望在屏幕上呈现的内容。 - - React 元素的对象表示如下: The object representation of React Element would be as follows: ```javascript @@ -394,7 +373,6 @@ ``` The above `React.createElement()` function returns an object: - 上面的 `React.createElement()` 函数会返回一个对象。 ``` { @@ -407,25 +385,19 @@ ``` And finally it renders to the DOM using `ReactDOM.render()`: - 最终使用 `ReactDOM.render()` 方法渲染到 DOM: ```html
Login
``` - Whereas a **component** can be declared in several different ways. It can be a class with a `render()` method. Alternatively, in simple cases, it can be defined as a function. In either case, it takes props as an input, and returns an JSX tree as the output: - - 然而一个组件可以以多种不同方式进行声明。它可以是一个含有 `render()` 方法的类。在简单的场景中,它能被定义成函数。在其它场景,它接收 props - 作为输入,返回 JSX 树作为输出: + Whereas a **component** can be declared in several different ways. It can be a class with a `render()` method. Alternatively, in simple cases, it can be defined as a function. In either case, it takes props as an input, and returns a JSX tree as the output: ```javascript const Button = ({ onLogin }) =>
``` - Then JSX gets transpiled to `React.createElement()` function tree: - - 接着 JSX 被转译为 `React.createElement()` 函数树: + Then JSX gets transpiled to a `React.createElement()` function tree: ```javascript const Button = ({ onLogin }) => React.createElement( @@ -438,15 +410,12 @@ 5. ### How to create components in React? There are two possible ways to create a component. - 这里有两种可行方式来创建一个组件: 1. **Function Components:** This is the simplest way to create a component. Those are pure JavaScript functions that accept props object as first parameter and return React elements: - 1. **Function Components:** 这是创建组件最简单的方式 - ```jsx harmony function Greeting({ message }) { - return

{`Hello, ${message}`}

+ return

{`Hello, ${message}`}


 } ``` @@ -477,12 +446,12 @@ class User extends React.Component { constructor(props) { super(props) - + this.state = { message: 'Welcome to React world' } } - + render() { return (
@@ -492,9 +461,9 @@ } } ``` - + ![state](images/state.jpg) - + State is similar to props, but it is private and fully controlled by the component. i.e, It is not accessible to any component other than the one that owns and sets it. 9. ### What are props in React? @@ -1109,7 +1078,7 @@ 45. ### Why React uses `className` over `class` attribute? - `class` is a keyword in JavaSript, and JSX is an extension of JavaScript. That's the principal reason why React uses `className` instead of `class`. Pass a string as the `className` prop. + `class` is a keyword in JavaScript, and JSX is an extension of JavaScript. That's the principal reason why React uses `className` instead of `class`. Pass a string as the `className` prop. ```jsx harmony render() { @@ -3833,6 +3802,7 @@ handleSubmit = () => { console.log("Input Value is: ", this.input.value) } + ``` render () { @@ -3847,19 +3817,19 @@ } } ``` - + But our expectation is for the ref callback to get called once, when the component mounts. One quick fix is to use the ES7 class property syntax to define the function - + ```jsx class UserForm extends Component { handleSubmit = () => { console.log("Input Value is: ", this.input.value) } - + setSearchInput = (input) => { this.input = input } - + render () { return (
@@ -3879,6 +3849,7 @@ 217. ### What are HOC factory implementations? There are two main ways of implementing HOCs in React. 1. Props Proxy (PP) and 2. Inheritance Inversion (II). They follow different approaches for manipulating the *WrappedComponent*. + **Props Proxy** In this approach, the render method of the HOC returns a React Element of the type of the WrappedComponent. We also pass through the props that the HOC receives, hence the name **Props Proxy**. @@ -3894,6 +3865,7 @@ } ``` **Inheritance Inversion** + In this approach, the returned HOC class (Enhancer) extends the WrappedComponent. It is called Inheritance Inversion because instead of the WrappedComponent extending some Enhancer class, it is passively extended by the Enhancer. In this way the relationship between them seems **inverse**. ```jsx @@ -4173,7 +4145,7 @@ The render() method is the only required method in a class component. i.e, All methods other than render method are optional for a class component. 239. ### What are the possible return types of render method? Below are the list of following types used and return from render method, - 1. **React elements:** Elements that instruct React to render a DOM node. It includes html elements such as
and user defined elements. + 1. **React elements:** Elements that instruct React to render a DOM node. It includes html elements such as `
` and user defined elements. 2. **Arrays and fragments:** Return multiple elements to render as Arrays and Fragments to wrap multiple elements 3. **Portals:** Render children into a different DOM subtree. 4. **String and numbers:** Render both Strings and Numbers as text nodes in the DOM @@ -5046,6 +5018,7 @@ ```javascript npm install bootstrap `` + ``` 3. React Bootstrap Package: In this case, you can add Bootstrap to our React app is by using a package that has rebuilt Bootstrap components to work particularly as React components. Below packages are popular in this category, 1. react-bootstrap @@ -5064,4 +5037,40 @@ 9. Netflix 10. PayPal 301. ### Is it recommended to use CSS In JS technique in React? - React does not have any opinion about how styles are defined but if you are a beginner then good starting point is to define your styles in a separate *.css file as usual and refer to them using className. This functionality is not part of React but came from third-party libraries. But If you want to try a different approach(CSS-In-JS) then styled-components library is a good option. \ No newline at end of file + React does not have any opinion about how styles are defined but if you are a beginner then good starting point is to define your styles in a separate *.css file as usual and refer to them using className. This functionality is not part of React but came from third-party libraries. But If you want to try a different approach(CSS-In-JS) then styled-components library is a good option. +302. ### Do I need to rewrite all my class components with hooks? + No. But you can try Hooks in a few components(or new components) without rewriting any existing code. Because there are no plans to remove classes in ReactJS. +303. ### How to fetch data with React Hooks? + The effect hook called `useEffect` is used to fetch the data with axios from the API and to set the data in the local state of the component with the state hook’s update function. + Let's take an example in which it fetches list of react articles from the API + ```javascript + import React, { useState, useEffect } from 'react'; + import axios from 'axios'; + + function App() { + const [data, setData] = useState({ hits: [] }); + + useEffect(async () => { + const result = await axios( + 'http://hn.algolia.com/api/v1/search?query=react', + ); + + setData(result.data); + }, []); + + return ( + + ); + } + + export default App; + ``` + Remember we provided an empty array as second argument to the effect hook to avoid activating it on component updates but only for the mounting of the component. i.e, It fetches only for component mount. +304. ### Is Hooks cover all use cases for classes? + Hooks doesn't cover all use cases of classes but there is a plan to add them soon. Currently there are no Hook equivalents to the uncommon **getSnapshotBeforeUpdate** and **componentDidCatch** lifecycles yet. diff --git a/README.md b/README.md index 454048d..b422d1f 100755 --- a/README.md +++ b/README.md @@ -9,10 +9,21 @@ 这里再次感谢 **[liaoyongfu](https://github.com/liaoyongfu)** 的大力支持🌹! +**阅读更多关于 Angular、TypeScript、Node.js/Java 、Spring 等技术文章,欢迎访问我的个人博客或关注我的公众号 —— [全栈修仙之路](http://www.semlinker.com/)** + +![fer_road_qrcode](./images/fer_road_qrcode.jpg) + +<<前端进阶篇 v1.1>> PDF 出炉了 — 「阿宝哥」,精心准备的 9 万多字 242 页的前端进阶资料。发布后 5 天内下载量为 **3170**。 + + + +点击此 [全栈修仙之路 - 前端进阶篇](http://book.bugstack.cn/#s/6I-ldR3A) 链接,即可免费下载电子书。 + ### 目录 + | 序号. | 问题 | -| --- | --------- | +| --- | --------- | | | [Core React](#core-react) | |1 | [什么是 React?](#什么是-react) | |2 | [React 的主要特点是什么?](#react-的主要特点是什么) | @@ -31,7 +42,7 @@ |15 | [如何将参数传递给事件处理程序或回调函数?](#如何将参数传递给事件处理程序或回调函数) | |16 | [React 中的合成事件是什么?](#react-中的合成事件是什么) | |17 | [什么是内联条件表达式?](#什么是内联条件表达式) | -|18 | [什么是 "key" 属性,在元素数组中使用它们有什么好处?](#什么是-"key"-属性在元素数组中使用它们有什么好处) | +|18 | [什么是 "key" 属性,在元素数组中使用它们有什么好处?](#什么是-key-属性在元素数组中使用它们有什么好处) | |19 | [refs 有什么用?](#refs-有什么用) | |20 | [如何创建 refs?](#如何创建-refs) | |21 | [什么是 forward refs?](#什么是-forward-refs) | @@ -322,6 +333,9 @@ |299 | [如何为 React 应用程序添加 bootstrap?](#如何为-react-应用程序添加-bootstrap) | |300 | [你能否列出使用 React 作为前端框架的顶级网站或应用程序?](#你能否列出使用-react-作为前端框架的顶级网站或应用程序) | |301 | [是否建议在 React 中使用 CSS In JS 技术?](#是否建议在-react-中使用-css-in-js-技术) | +|302 | [我需要用 hooks 重写所有类组件吗?](#我需要用-hooks-重写所有类组件吗) | +|303 | [如何使用 React Hooks 获取数据?](#如何使用-react-hooks-获取数据) | +|304 | [Hooks 是否涵盖了类的所有用例?](#hooks-是否涵盖了类的所有用例) | ## Core React @@ -345,7 +359,7 @@ * 考虑到真实的 DOM 操作成本很高,它使用 VirtualDOM 而不是真实的 DOM。 * 支持服务端渲染。 * 遵循单向数据流或数据绑定。 - * 使用可重用/可组合的 UI 组件开发视图。 + * 使用可复用/可组合的 UI 组件开发视图。 **[⬆ 返回顶部](#目录)** @@ -431,6 +445,10 @@ ) ``` + 阅读资源: + + 1. [为什么React元素有一个$$typeof属性?](https://overreacted.io/zh-hans/why-do-react-elements-have-typeof-property/) + **[⬆ 返回顶部](#目录)** 5. ### 如何在 React 中创建组件? @@ -455,6 +473,27 @@ } ``` + 通过以上任意方式创建的组件,可以这样使用: + + ```jsx + + ``` + + 在 React 内部对函数组件和类组件的处理方式是不一样的,如: + + ```javascript + // 如果 Greeting 是一个函数 + const result = Greeting(props); //

Hello

+ + // 如果 Greeting 是一个类 + const instance = new Greeting(props); // Greeting {} + const result = instance.render(); //

Hello

+ ``` + + 阅读资源: + + 1. [React 如何区分 Class 和 Function?](https://overreacted.io/zh-hans/how-does-react-tell-a-class-from-a-function/) + **[⬆ 返回顶部](#目录)** 6. ### 何时使用类组件和函数组件? @@ -465,7 +504,7 @@ 7. ### 什么是 Pure Components? - `React.PureComponent` 与 `React.Component` 完全相同,只是它为你处理了 `shouldComponentUpdate()` 方法。当属性或状态发生变化时,PureComponent 将对属性和状态进行浅比较。另一方面,普通组件不会将当前的属性和状态与新的属性和状态进行比较。因此,在默认情况下,每当调用 `shouldComponentUpdate` 时,组件将重新渲染。 + `React.PureComponent` 与 `React.Component` 完全相同,只是它为你处理了 `shouldComponentUpdate()` 方法。当属性或状态发生变化时,PureComponent 将对属性和状态进行**浅比较**。另一方面,一般的组件不会将当前的属性和状态与新的属性和状态进行比较。因此,在默认情况下,每当调用 `shouldComponentUpdate` 时,默认返回 true,所以组件都将重新渲染。 **[⬆ 返回顶部](#目录)** @@ -541,14 +580,14 @@ 11. ### 我们为什么不能直接更新状态? - 如果你尝试直接更新状态,则不会重新渲染组件? + 如果你尝试直接改变状态,那么组件将不会重新渲染。 ```javascript //Wrong this.state.message = 'Hello world' ``` - 而是使用 `setState()` 方法。它调度组件状态对象的更新。当状态更改时,组件通过重新渲染来响应。 + 正确方法应该是使用 `setState()` 方法。它调度组件状态对象的更新。当状态更改时,组件通将会重新渲染。 ```javascript //Correct @@ -572,12 +611,13 @@ 阅读资源: 1. [掘金 - 揭密React setState](https://juejin.im/post/5b87d14e6fb9a01a18268caf) + 2. [setState 如何知道该做什么?](https://overreacted.io/zh-hans/how-does-setstate-know-what-to-do/) **[⬆ 返回顶部](#目录)** 13. ### HTML 和 React 事件处理有什么区别? - 1. 在 HTML 中事件名必须小写: + 1. 在 HTML 中事件名必须小写: ```html

} ``` + + 当然如果只是想判断 if,可以如下直接判断: + + ``` + { + isLogin && Your have been login! + } + ``` + + 在上面的代码中,不需要使用`isLogin ? Your have been login! : null`这样的形式。 **[⬆ 返回顶部](#目录)** @@ -1254,6 +1304,8 @@ return {'Menu'} } ``` + + 在实际项目中,我们经常使用[classnames](https://github.com/JedWatson/classnames)来方便我们操作`className`。 **[⬆ 返回顶部](#目录)** @@ -1273,7 +1325,7 @@ } ``` - 以下是简介语法,但是在一些工具中还不支持: + 以下是简洁语法,但是在一些工具中还不支持: ```jsx render() { @@ -1396,7 +1448,7 @@ 2. 对于 Web 开发初学者来说,有一个学习曲线。 3. 将 React 集成到传统的 MVC 框架中需要一些额外的配置。 4. 代码复杂性随着内联模板和 JSX 的增加而增加。 - 5. 太多较小的组件导致过度工程化或样板文件。 + 5. 如果有太多的小组件可能增加项目的庞大和复杂。 **[⬆ 返回顶部](#目录)** @@ -1641,7 +1693,7 @@ } } ``` - + **[⬆ 返回顶部](#目录)** 67. ### 如何有条件地渲染组件? @@ -2155,6 +2207,10 @@ 在 `constructor()` 函数之外,访问 `this.props` 属性会显示相同的值。 + 阅读资源: + + 1. [为什么我们要写 super(props)?](https://overreacted.io/zh-hans/why-do-we-write-super-props/) + **[⬆ 返回顶部](#目录)** 92. ### 在 JSX 中如何进行循环? @@ -2205,7 +2261,7 @@ 94. ### 什么是 React proptype 数组? - 如果要将对象数组传递给具有特定形状的组件,请使用 `React.PropTypes.shape()` 作为 `React.PropTypes.arrayOf()` 的参数。 + 如果你要规范具有特定对象格式的数组的属性,请使用 `React.PropTypes.shape()` 作为 `React.PropTypes.arrayOf()` 的参数。 ```javascript ReactComponent.propTypes = { @@ -2408,7 +2464,7 @@ React.render(, document.getElementById('container')) ``` - + **[⬆ 返回顶部](#目录)** 106. ### 为什么你不能更新 React 中的 props? @@ -2480,7 +2536,6 @@ 109. ### 为什么函数比对象更适合于 `setState()`? - React may batch multiple `setState()` calls into a single update for performance. Because `this.props` and `this.state` may be updated asynchronously, you should not rely on their values for calculating the next state. 出于性能考虑,React 可能将多个 `setState()` 调用合并成单个更新。这是因为我们可以异步更新 `this.props` 和 `this.state`,所以不应该依赖它们的值来计算下一个状态。 以下的 counter 示例将无法按预期更新: @@ -2852,7 +2907,7 @@ 129. ### 什么是 React Router? - React Router 是一个基于 React 的强大的路由库,可以帮助您快速地向应用添加新的屏幕和流,同时保持 URL 与页面上显示的内容同步。 + React Router 是一个基于 React 之上的强大路由库,可以帮助您快速地向应用添加视图和数据流,同时保持 UI 与 URL 同步。 **[⬆ 返回顶部](#目录)** @@ -3520,7 +3575,7 @@ 164. ### Redux 中连接装饰器的 `at` 符号的目的是什么? - **@**符号实际上是用于表示装饰器的 JavaScript 表达式。*装饰器*可以在设计时注释和修改类和属性。 + **@** 符号实际上是用于表示装饰器的 JavaScript 表达式。*装饰器*可以在设计时注释和修改类和属性。 让我们举个例子,在没有装饰器的情况下设置 Redux 。 @@ -3662,7 +3717,7 @@ **展示组件**是一个类或功能组件,用于描述应用程序的展示部分。 - **容器组件**是连接到 Redux Store的组件的非正式术语。容器组件*订阅* Redux 状态更新和*dispatch*操作,它们通常不呈现 DOM 元素; 他们将渲染委托给展示性的子组件。 + **容器组件**是连接到 Redux Store的组件的非正式术语。容器组件*订阅* Redux 状态更新和*dispatch*操作,它们通常不呈现 DOM 元素;他们将渲染委托给展示性的子组件。 **[⬆ 返回顶部](#目录)** @@ -3925,7 +3980,7 @@ 189. ### 如何测试 React Native 应用程序? - React Native 只能在 iOS 和 Android 等移动模拟器中进行测试。您可以使用 expo app(https://expo.io)在移动设备上运行该应用程序。如果使用 QR 代码进行同步,则您的移动设备和计算机应位于同一个无线网络中。 + React Native 只能在 iOS 和 Android 等移动模拟器中进行测试。您可以使用 expo app([https://expo.io](https://expo.io))在移动设备上运行该应用程序。如果使用 QR 代码进行同步,则您的移动设备和计算机应位于同一个无线网络中。 **[⬆ 返回顶部](#目录)** @@ -4007,7 +4062,7 @@ 可用于不同浏览器或环境的官方扩展。 1. **Chrome插件** 2. **Firefox插件** - 3. **独立应用** (Safari, React Native, 等) + 3. **独立应用** ( Safari,React Native 等) **[⬆ 返回顶部](#目录)** @@ -4252,7 +4307,7 @@ 210. ### Redux 只能与 React 一起使用么? - Redux 可以用做任何 UI 层的数据存储。最常见的应用场景是 React 和 React Native,但也有一些 bindings 可用于 AngularJS,Angular 2,Vue,Mithril 等项目。Redux 只提供了一种订阅机制,任何其他代码都可以使用它。 + Redux 可以用做任何 UI 层的数据存储。最常见的应用场景是 React 和 React Native,但也有一些 bindings 可用于 AngularJS,Angular 2,Vue,Mithril 等项目。Redux 只提供了一种订阅机制,任何其他代码都可以使用它。 **[⬆ 返回顶部](#目录)** @@ -4309,7 +4364,7 @@ ) ``` - + **[⬆ 返回顶部](#目录)** 215. ### 为什么不建议使用内联引用回调或函数? @@ -4321,7 +4376,7 @@ handleSubmit = () => { console.log("Input Value is: ", this.input.value) } - + render () { return ( @@ -4334,19 +4389,19 @@ } } ``` - + 但我们期望的是当组件挂载时,ref 回调只会被调用一次。一个快速修复的方法是使用 ES7 类属性语法定义函数。 - + ```jsx class UserForm extends Component { handleSubmit = () => { console.log("Input Value is: ", this.input.value) } - + setSearchInput = (input) => { this.input = input } - + render () { return ( @@ -4371,12 +4426,12 @@ 217. ### 什么是 HOC 工厂实现? 在 React 中实现 HOC 有两种主要方式。 1.属性代理(PP)和 2.继承倒置(II)。他们遵循不同的方法来操纵*WrappedComponent*。 - **属性代理** + **属性代理** 在这种方法中,HOC 的 render 方法返回 WrappedComponent 类型的 React 元素。我们通过 HOC 收到 props,因此定义为**属性代理**。 ```jsx - + function ppHOC(WrappedComponent) { return class PP extends React.Component { render() { @@ -4432,7 +4487,7 @@ import ReactDOM from 'react-dom'; import App from './App'; import registerServiceWorker from './registerServiceWorker'; - + ReactDOM.render(, document.getElementById('root')); registerServiceWorker(); ``` @@ -4457,7 +4512,7 @@ ```jsx const OtherComponent = React.lazy(() => import('./OtherComponent')); - + function MyComponent() { return (
@@ -4541,24 +4596,24 @@ ```jsx class Counter extends Component { state = { value: 0 }; - + handleIncrement = () => { this.setState(prevState => ({ value: prevState.value + 1 })); }; - + handleDecrement = () => { this.setState(prevState => ({ value: prevState.value - 1 })); }; - + render() { return (
{this.state.value} - +
@@ -4575,11 +4630,11 @@ ```jsx import { useState } from 'react'; - + function Example() { // Declare a new state variable, which we'll call "count" const [count, setCount] = useState(0); - + return (

You clicked {count} times

@@ -4592,7 +4647,7 @@ ``` 阅读资源: - + 1. [掘金 - 30分钟精通React Hooks](https://juejin.im/post/5be3ea136fb9a049f9121014) **[⬆ 返回顶部](#目录)** @@ -4696,7 +4751,7 @@ super(props); this.state = { error: null }; } - + handleClick = () => { try { // Do something that could throw @@ -4704,7 +4759,7 @@ this.setState({ error }); } } - + render() { if (this.state.error) { return

Caught an error.

@@ -4819,11 +4874,11 @@ class MyButton extends React.Component { // ... } - + MyButton.defaultProps = { color: 'red' }; - + ``` 如果未设置 props.color,则会使用默认值 `red`。 也就是说,每当你试图访问 color 属性时,它都使用默认值。 @@ -4860,18 +4915,18 @@ super(props); this.state = { hasError: false }; } - + static getDerivedStateFromError(error) { // Update state so the next render will show the fallback UI. return { hasError: true }; } - + render() { if (this.state.hasError) { // You can render any custom fallback UI return

Something went wrong.

; } - + return this.props.children; } } @@ -4903,7 +4958,7 @@ 247. ### displayName 类属性的用途是什么? displayName 被用于调试信息。通常,你不需要显式设置它,因为它是从定义组件的函数或类的名称推断出来的。如果出于调试目的或在创建高阶组件时显示不同的名称,可能需要显式设置它。 - + 例如,若要简化调试,请选择一个显示名称,以表明它是 withSubscription HOC 的结果。 ```javascript @@ -4912,7 +4967,7 @@ WithSubscription.displayName = `WithSubscription(${getDisplayName(WrappedComponent)})`; return WithSubscription; } - + function getDisplayName(WrappedComponent) { return WrappedComponent.displayName || WrappedComponent.name || 'Component'; } @@ -4943,13 +4998,13 @@ **moduleA.js** ```javascript const moduleA = 'Hello'; - + export { moduleA }; ``` **App.js** ```javascript import React, { Component } from 'react'; - + class App extends Component { handleClick = () => { import('./moduleA') @@ -4960,7 +5015,7 @@ // Handle failure }); }; - + render() { return (
@@ -4969,7 +5024,7 @@ ); } } - + export default App; ``` @@ -5093,16 +5148,16 @@ class LogProps extends React.Component { // ... } - + function forwardRef(props, ref) { return ; } - + // Give this component a more helpful display name in DevTools. // e.g. "ForwardRef(logProps(MyComponent))" const name = Component.displayName || Component.name; forwardRef.displayName = `logProps(${name})`; - + return React.forwardRef(forwardRef); } ``` @@ -5115,7 +5170,7 @@ ```javascript - + ``` @@ -5168,14 +5223,14 @@ 260. ### 如何防止函数被多次调用? 如果你使用一个事件处理程序,如 **onClick or onScroll** 并希望防止回调被过快地触发,那么你可以限制回调的执行速度。 - + 这可以通过以下可能的方式实现: 1. **Throttling:** 基于时间的频率进行更改。例如,它可以使用 lodash 的 _.throttle 函数。 2. **Debouncing:** 在一段时间不活动后发布更改。例如,可以使用 lodash 的 _.debounce 函数。 3. **RequestAnimationFrame throttling:** 基于 requestAnimationFrame 的更改。例如,可以使用 raf-schd。 - > 注意:_.debounce , _.throttle 和 raf-schd 都提供了一个 cancel 方法来取消延迟回调。所以需要调用 componentWillUnmount,或者对代码进行检查来保证在延迟函数有效期间内组件始终挂载。 + > 注意:_.debounce, _.throttle 和 raf-schd 都提供了一个 cancel 方法来取消延迟回调。所以需要调用 componentWillUnmount,或者对代码进行检查来保证在延迟函数有效期间内组件始终挂载。 **[⬆ 返回顶部](#目录)** @@ -5206,7 +5261,7 @@ ); ReactDOM.render(element, document.getElementById('root')); } - + setInterval(tick, 1000); ``` @@ -5222,13 +5277,12 @@ } ``` - 上面的函数称为 "pure" 函数,因为它不会尝试更改输入,并总是为相同的输入返回相同的结果。因此,React 有一条规则,即"所有 React 组件的行为都必须像纯函数一样。" + 上面的函数称为“纯”函数,因为它不会尝试更改输入,并总是为相同的输入返回相同的结果。因此,React 有一条规则,即“所有 React 组件的行为都必须像纯函数一样”。 **[⬆ 返回顶部](#目录)** 264. ### 你认为状态更新是如何合并的? - When you call setState() in the component, React merges the object you provide into the current state. For example, let us take a facebook user with posts and comments details as state variables, 当你在组件中调用 setState() 方法时,React 会将提供的对象合并到当前状态。例如,让我们以一个使用帖子和评论详细信息的作为状态变量的 Facebook 用户为例: ```javascript @@ -5250,7 +5304,7 @@ posts: response.posts }); }); - + fetchComments().then(response => { this.setState({ comments: response.comments @@ -5285,7 +5339,7 @@ if (!props.loggedIn) { return null; } - + return (
welcome, {props.name} @@ -5300,7 +5354,7 @@ super(props); this.state = {loggedIn: false, name: 'John'}; } - + render() { return (
@@ -5396,7 +5450,7 @@ import React, { Component } from 'react'; import './App.css'; import '@vaadin/vaadin-date-picker'; - + class App extends Component { render() { return ( @@ -5406,7 +5460,7 @@ ); } } - + export default App; ``` @@ -5437,9 +5491,9 @@ ```javascript import loadable from '@loadable/component' - + const OtherComponent = loadable(() => import('./OtherComponent')) - + function MyComponent() { return (
@@ -5459,7 +5513,7 @@ ```javascript const OtherComponent = React.lazy(() => import('./OtherComponent')); - + function MyComponent() { return (
@@ -5482,10 +5536,10 @@ ```javascript import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'; import React, { Suspense, lazy } from 'react'; - + const Home = lazy(() => import('./routes/Home')); const About = lazy(() => import('./routes/About')); - + const App = () => ( Loading...
}> @@ -5543,7 +5597,7 @@ 当在组件树中的组件没有匹配到在其上方的 Provider 时,才会使用 defaultValue 参数。这有助于在不包装组件的情况下单独测试组件。下面的代码段提供了默认的主题值 Luna。 ```javascript - const defaultTheme = "Luna"; + const defaultTheme = "Luna"; const MyContext = React.createContext(defaultTheme); ``` @@ -5622,7 +5676,7 @@ } } ``` - + 可以通过把 value 的值提升到父状态中来解决这个问题: ```javascript @@ -5633,7 +5687,7 @@ value: {something: 'something'}, }; } - + render() { return ( @@ -5659,15 +5713,15 @@ console.log('old props:', prevProps); console.log('new props:', this.props); } - + render() { const {forwardedRef, ...rest} = this.props; - + // Assign the custom prop "forwardedRef" as a ref return ; } } - + return React.forwardRef((props, ref) => { return ; }); @@ -5681,7 +5735,7 @@ focus() { // ... } - + // ... } export default logProps(FancyButton); @@ -5691,7 +5745,7 @@ ```javascript import FancyButton from './FancyButton'; - + const ref = React.createRef(); ref.current.focus(); Hello {this.props.message}
; } } - + ReactDOM.render( , document.getElementById('root') @@ -5767,7 +5821,7 @@ return React.createElement('div', null, `Hello ${this.props.message}`); } } - + ReactDOM.render( React.createElement(Greeting, {message: 'World'}, null), document.getElementById('root') @@ -5830,7 +5884,7 @@
  • Duke
  • Villanova
  • - +
    • Connecticut
    • Duke
    • @@ -5859,7 +5913,7 @@

      The mouse position is {mouse.x}, {mouse.y}

      )}/> ``` - + 实际上,以上的 children 属性不一定需要在 JSX 元素的 `attributes` 列表中命名。反之,你可以将它直接放在元素内部: ```javascript @@ -5888,7 +5942,7 @@ 292. ### 如何使用渲染属性创建 HOC? - 可以使用带有渲染属性的常规组件实现大多数高阶组件(HOC)。例如,如果希望使用 withMouse HOC 而不是 组件,则你可以使用带有渲染属性的常规 组件轻松创建一个 HOC 组件。 + 可以使用带有渲染属性的常规组件实现大多数高阶组件(HOC)。例如,如果希望使用 withMouse HOC 而不是 `` 组件,则你可以使用带有渲染属性的常规 `` 组件轻松创建一个 HOC 组件。 ```javascript function withMouse(Component) { @@ -6015,4 +6069,55 @@ React 对如何定义样式没有任何意见,但如果你是初学者,那么好的起点是像往常一样在单独的 *.css 文件中定义样式,并使用类名引用它们。此功能不是 React 的一部分,而是来自第三方库。但是如果你想尝试不同的方法(JS中的CSS),那么 styled-components 库是一个不错的选择。 - **[⬆ 返回顶部](#目录)** \ No newline at end of file + **[⬆ 返回顶部](#目录)** + +302. ### 我需要用 hooks 重写所有类组件吗? + + 不需要。但你可以在某些组件(或新组件)中尝试使用 hooks,而无需重写任何已存在的代码。因为在 ReactJS 中目前没有移除 classes 的计划。 + + **[⬆ 返回顶部](#目录)** + +303. ### 如何使用 React Hooks 获取数据? + + 名为 useEffect 的 effect hook 可用于使用 axios 从 API 中获取数据,并使用 useState 钩子提供的更新函数设置组件本地状态中的数据。让我们举一个例子,它从 API 中获取 react 文章列表。 + + ```jsx + import React, { useState, useEffect } from 'react'; + import axios from 'axios'; + + function App() { + const [data, setData] = useState({ hits: [] }); + + useEffect(async () => { + const result = await axios( + 'http://hn.algolia.com/api/v1/search?query=react', + ); + + setData(result.data); + }, []); + + return ( + + ); + } + + export default App; + ``` + + 记住,我们为 effect hook 提供了一个空数组作为第二个参数,以避免在组件更新时再次激活它,它只会在组件挂载时被执行。比如,示例中仅在组件挂载时获取数据。 + + **[⬆ 返回顶部](#目录)** + +304. ### Hooks 是否涵盖了类的所有用例? + + Hooks 并没有涵盖类的所有用例,但是有计划很快添加它们。目前,还没有与不常见的 getSnapshotBeforeUpdate 和componentDidCatch 生命周期等效的钩子。 + + +**[⬆ 返回顶部](#目录)** + diff --git a/images/fer_road_qrcode.jpg b/images/fer_road_qrcode.jpg new file mode 100644 index 0000000..ccfb3dc Binary files /dev/null and b/images/fer_road_qrcode.jpg differ diff --git a/images/frontend-advanced-intro-v1.1.jpg b/images/frontend-advanced-intro-v1.1.jpg new file mode 100644 index 0000000..cb01e93 Binary files /dev/null and b/images/frontend-advanced-intro-v1.1.jpg differ