- props和state的区别
props是只读属性,不能被修改,是传递给组件的(类似于形参);state是在组件内被组件自己管理的(类似于在一个函数内声明的变量), 包含了随时可能发生变化的数据, 由用户自定义。
如果某些值未用于渲染或数据流(例如,计时器 ID),则不必将其设置为 state,此类值可以在组件实例上定义。
- 函数组件&&class组件&&Hook
Hook是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及生命周期等特性。(只能在函数最外层调用 Hook;只能在 React 的函数组件中调用 Hook。)
没有Hook时函数组件接收props作为参数,返回React组件,没有状态和生命周期方法。
class组件使用ES6语法
函数组件的性能比类组件的性能要高,因为类组件使用的时候要实例化,而函数组件直接执行函数取返回结果即可。
- 什么是JSX
JSX,是一个 JavaScript 的语法扩展。React 认为渲染逻辑本质上与其他 UI 逻辑内在耦合,比如,在 UI 中需要绑定处理事件、在某些时刻状态发生变化时需要通知到 UI,以及需要在 UI 中展示准备好的数据。
React 并没有采用将标记与逻辑进行分离到不同文件这种人为地分离方式,而是通过将二者共同存放在称之为“组件”的松散耦合单元之中,来实现关注点分离。
- setState
setState()
将对组件 state 的更改排入队列,并通知 React 需要使用更新后的 state 重新渲染此组件及其子组件。setState()
并不总是立即更新组件。它会批量推迟更新。请使用 componentDidUpdate
或者 setState
的回调函数(setState(updater, callback)
),这两种方式都可以保证在应用更新后触发。
setState()
的第一个参数除了接受函数外,还可以接受对象类型
setState()
的第二个参数为可选的回调函数,它将在 setState
完成合并并重新渲染组件后执行。通常,我们建议使用 componentDidUpdate()
来代替此方式。
如果后续状态取决于当前状态,我们建议使用 updater 函数的形式代替
-
性能优化
-
使用生产版本
-
shouldComponentUpdate或
[React.PureComponent](https://zh-hans.reactjs.org/docs/react-api.html#reactpurecomponent)
-
key
React更新列表时会顺序遍历元素,在子元素列表末尾新增元素时,更新开销比较小;如果只是简单的将新增元素插入到表头,那么更新开销会比较大。
当子元素拥有 key 时,React 使用 key 来匹配原有树上的子元素以及最新树上的子元素。
组件实例是基于它们的 key 来决定是否更新以及复用,你也可以使用元素在数组中的下标作为 key。这个策略在元素不进行重新排序时比较合适,如果有顺序修改,diff 就会变得慢。
key 帮助 React 识别出被修改、添加或删除的 item。应当给数组内的每个元素都设定 key,以使元素具有固定身份标识。
- 高阶组件(HOC)(Higher-Order Component)
例如 Redux 的 [connect](https://github.com/reduxjs/react-redux/blob/master/docs/api/connect.md#connect)
我们需要一个抽象,允许我们在一个地方定义这个逻辑,并在许多组件之间共享它。这正是高阶组件擅长的地方。
请注意,HOC 不会修改传入的组件,也不会使用继承来复制其行为。相反,HOC 通过将组件
包装在容器组件中来组成新组件。HOC 是纯函数,没有副作用。
HOC 应该透传与自身无关的 props。
- 虚拟DOM
Virtual DOM 是一种编程概念。在这个概念里, UI 以一种理想化的,或者说“虚拟的”表现形式被保存于内存中,并通过如 ReactDOM 等类库使之与“真实的” DOM 同步。
- refs
Refs 提供了一种方式,允许我们访问 DOM 节点或在 render 方法中创建的 React 元素。
适用refs的情况:
- 管理焦点,文本选择或媒体播放。
- 触发强制动画。
- 集成第三方 DOM 库。
使用refs的两种方式
- 使用
React.createRef()
创建,对该节点的引用可以在 ref 的current
属性中被访问 - 回调 refs:这个函数中接受 React 组件实例或 HTML DOM 元素作为参数,我们将其绑定到 this 指针以便在其他的类函数中使用。
默认情况下,你不能在函数组件上使用 ref
属性,因为它们没有实例,但函数式组件同样能够利用闭包暂存其值。
关于回调 refs 的说明:
如果 ref
回调函数是以内联函数的方式定义的,在更新过程中它会被执行两次,第一次传入参数 null
,然后第二次会传入参数 DOM 元素。这是因为在每次渲染时会创建一个新的函数实例,所以 React 清空旧的 ref 并且设置新的。通过将 ref 的回调函数定义成 class 的绑定函数的方式可以避免上述问题,但是大多数情况下它是无关紧要的。
-
生命周期
-
render
render()
方法是 class 组件中唯一必须实现的方法。
render()
函数应该为纯函数,这意味着在不修改组件 state 的情况下,每次调用时都返回相同的结果,并且它不会直接与浏览器交互。
- constructor
如果不初始化 state 或不进行方法绑定,则不需要为 React 组件实现构造函数。
通常,在 React 中,构造函数仅用于以下两种情况:
-
通过给
this.state
赋值对象来初始化内部 state。 -
为事件处理函数绑定实例
-
componentDidMount
componentDidMount()
会在组件挂载后(插入 DOM 树中)立即调用。依赖于 DOM 节点的初始化应该放在这里。如需通过网络请求获取数据,此处是实例化请求的好地方。也可以在此添加订阅。
你可以在 componentDidMount() 里直接调用 setState()。它将触发额外渲染,但此渲染会发生在浏览器更新屏幕之前。如此保证了即使在 render() 两次调用的情况下,用户也不会看到中间状态。如果你的渲染依赖于 DOM 节点的大小或位置,比如实现 modals 和 tooltips 等情况下,你可以使用此方式处理
- componentDidUpdate
componentDidUpdate() 会在更新后会被立即调用。首次渲染不会执行此方法。
你也可以在 componentDidUpdate() 中直接调用 setState(),但请注意它必须被包裹在一个条件语句里,正如上述的例子那样进行处理,否则会导致死循环。它还会导致额外的重新渲染,虽然用户不可见,但会影响组件性能。
- componentWillUnmount
componentWillUnmount() 会在组件卸载及销毁之前直接调用。在此方法中执行必要的清理操作,例如,清除 timer,取消网络请求或清除在 componentDidMount() 中创建的订阅等。
componentWillUnmount() 中不应调用 setState(),因为该组件将永远不会重新渲染。组件实例卸载后,将永远不会再挂载它。
- shouldComponentUpdate
根据 shouldComponentUpdate() 的返回值,判断 React 组件的输出是否受当前 state 或 props 更改的影响。
不建议在 shouldComponentUpdate() 中进行深层比较或使用 JSON.stringify()。这样非常影响效率,且会损害性能。
- static getDerivedStateFromProps
getDerivedStateFromProps 会在调用 render 方法之前调用,并且在初始挂载及后续更新时都会被调用。它应返回一个对象来更新 state,如果返回 null 则不更新任何内容。
此方法适用于罕见的用例,即 state 的值在任何时候都取决于 props。例如,实现 组件可能很方便,该组件会比较当前组件与下一组件,以决定针对哪些组件进行转场动画。
此方法无权访问组件实例。不管原因是什么,都会在每次渲染前触发此方法。
- getSnapshotBeforeUpdate
getSnapshotBeforeUpdate() 在最近一次渲染输出(提交到 DOM 节点)之前调用。它使得组件能在发生更改之前从 DOM 中捕获一些信息(例如,滚动位置)。此生命周期的任何返回值将作为参数传递给 componentDidUpdate()。
- static getDerivedStateFromError
此生命周期会在后代组件抛出错误后被调用。 它将抛出的错误作为参数,并返回一个值以更新 state。
getDerivedStateFromError() 会在渲染阶段调用,因此不允许出现副作用。 如遇此类情况,请改用 componentDidCatch()。
- componentDidCatch
此生命周期在后代组件抛出错误后被调用。 它接收两个参数:
error
—— 抛出的错误。info
—— 带有componentStack
key 的对象,其中包含有关组件引发错误的栈信息。
componentDidCatch() 会在“提交”阶段被调用,因此允许执行副作用。 它应该用于记录错误之类的情况
如果 class 组件定义了生命周期方法 static getDerivedStateFromError() 或 componentDidCatch() 中的任何一个(或两者),它就成为了 Error boundaries。Error boundaries 是 React 组件,它会在其子组件树中的任何位置捕获 JavaScript 错误,并记录这些错误,展示降级 UI 而不是崩溃的组件树。Error boundaries 组件会捕获在渲染期间,在生命周期方法以及其整个树的构造函数中发生的错误。仅使用 Error boundaries 组件来从意外异常中恢复的情况;不要将它们用于流程控制。
- context
Context 提供了一个无需为每层组件手动添加 props,就能在组件树间进行数据传递的方法。
Context 设计目的是为了共享那些对于一个组件树而言是“全局”的数据,例如当前认证的用户、主题或首选语言。
Context 主要应用场景在于很多不同层级的组件需要访问同样一些的数据。
请谨慎使用,因为这会使得组件的复用性变差。
挂载在 class 上的 contextType 属性会被重赋值为一个由 React.createContext() 创建的 Context 对象。这能让你使用 this.context 来消费最近 Context 上的那个值。你可以在任何生命周期中访问到它,包括 render 函数中。
- portals
典型用例是当父组件有 overflow: hidden 或 z-index 样式时,但你需要子组件能够在视觉上“跳出”其容器。例如,对话框、悬浮卡以及提示框
- 代码分割
对你的应用进行代码分割能够帮助你“懒加载”当前用户所需要的内容,能够显著地提高你的应用性能。尽管并没有减少应用整体的代码体积,但你可以避免加载用户永远不需要的代码,并在初始加载的时候减少所需加载的代码量。
动态import()语法
React.lazy 函数能让你像渲染常规组件一样处理动态引入(的组件)。React.lazy 接受一个函数,这个函数需要动态调用 import()。它必须返回一个 Promise,该 Promise 需要 resolve 一个 default export 的 React 组件。
然后应在 Suspense 组件中渲染 lazy 组件,如此使得我们可以使用在等待加载 lazy 组件时做优雅降级(如 loading 指示器等)。
fallback 属性接受任何在组件加载过程中你想展示的 React 元素。
代码分割可以基于路由。
- 事件处理
React 元素的事件处理和 DOM 元素的很相似,但是有一点语法上的不同:
- React 事件的命名采用小驼峰式(camelCase),而不是纯小写。
- 使用 JSX 语法时你需要传入一个函数作为事件处理函数,而不是一个字符串。
- 在 React 中另一个不同点是你不能通过返回 false 的方式阻止默认行为。你必须显式的使用 preventDefault 。
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!