React 注意点

代码分割,使首屏页面加载的更快#

  • 根据情况采用代码分割(比如某个体积相对比较大的第三方库或插件(比如JS版的PDF预览库)只在单页应用(SPA)的某一个不是首页的页面使用了,这种情况就可以考虑代码分割,增加首屏的加载速度)
  • React 的懒加载
Copy
import React, { Suspense } from 'react'; const OtherComponent = React.lazy(() => import('./OtherComponent')); function MyComponent() { return ( <div> <Suspense fallback={<div>Loading...</div>}> <OtherComponent /> </Suspense> </div> ); }

如上代码中,通过 import()React.lazySuspense 共同一起实现了 React 的懒加载,也就是我们常说了运行时动态加载,即 OtherComponent 组件文件被拆分打包为一个新的包(bundle)文件,并且只会在 OtherComponent 组件渲染时,才会被下载到本地。

Ref#

  • React.createRef()

使用此方法来创建ref。将其赋值给一个变量,通过ref挂载在dom节点或组件上,该ref的current属性将能拿到dom节点或组件的实例

Copy
class Child extends React.Component{ constructor(props){ super(props); this.myRef=React.createRef(); } componentDidMount(){ console.log(this.myRef.current); } render(){ return <input ref={this.myRef}/> } }
  • React.forwardRef

用来创建子组件,以传递ref

Copy
//子组件(通过forwardRef方法创建) const Child=React.forwardRef((props,ref)=>( <input ref={ref} /> )); //父组件 class Father extends React.Component{ constructor(props){ super(props); this.myRef=React.createRef(); } componentDidMount(){ console.log(this.myRef.current); } render(){ return <Child ref={this.myRef}/> } }

context#

生成全局的数据,不用通过props 一层一层传递,而是组件间可以共享数据,可用 Redux 代替

const MyContext = React.createContext(defaultValue);

  • **Context.provider ==> 提供值并传值 **

<MyContext.Provider value={/* 某个值 */}>

Provider 接收一个 value 属性,传递给消费组件

  • Context.Consumer ==> 使用值,并可以更改context的值
Copy
<MyContext.Consumer> {value => /* 基于 context 值进行渲染*/} </MyContext.Consumer>

Fragments#

当一个组件返回多个元素时,不想增加额外的标签如 div 进行包裹时,可用 Fragments

Copy
render() { return ( <React.Fragment> <ChildA /> <ChildB /> <ChildC /> </React.Fragment> ); }

高阶组件(HOC)#

参数是组件,返回新的组件

Portals#

Portal 将子节点渲染到存在于父组件以外的 DOM 节点即可以被放置在 DOM 树中的任何地方。

ReactDOM.createPortal(child, container)

第一个参数(child)是任何可渲染的 React 子元素,例如一个元素,字符串或 fragment。第二个参数(container)是一个 DOM 元素。

一个 portal 的典型用例是当父组件有 overflow: hiddenz-index 样式时,但你需要子组件能够在视觉上“跳出”其容器。例如,对话框、悬浮卡以及提示框

Copy
export default const Portal = ({ children }) => { const el = useMemo(() => document.body, []); return ReactDOM.createPortal(children, el); };

React中的Diffing算法#

当对比两颗树时,React 首先比较两棵树的根节点。不同类型的根节点元素会有不同的形态。

如果根节点不同,React会拆卸原有的树,重新生成新的树,包括里面的组件都会全部销毁

比对同一类型的元素,React会保留Dom节点,仅比对及更新有改变的属性

对子节点进行递归时,在默认条件下,当递归 DOM 节点的子元素时,React 会同时遍历两个子元素的列表;当产生差异时,生成一个 mutation。

  • 在子元素列表 末尾 增加元素时:
Copy
<ul> <li>first</li> <li>second</li> </ul> <ul> <li>first</li> <li>second</li> <li>third</li> </ul>

这种情况的更变开销比较小,前面两个是一样的,不用变更,只需要在末尾增加一个就行了

  • 在子元素列表 头部 增加元素时:
Copy
<ul> <li>Duke</li> <li>Villanova</li> </ul> <ul> <li>Connecticut</li> <li>Duke</li> <li>Villanova</li> </ul>

这种开销会比较大,React 会针对每个子元素进行 mutate,这种情况下会导致性能问题

解决:

给列表增加key属性,当子元素拥有key时,React 使用 key 来匹配原有树上的子元素以及最新树上的子元素

Copy
<ul> <li key="2015">Duke</li> <li key="2016">Villanova</li> </ul> <ul> <li key="2014">Connecticut</li> <li key="2015">Duke</li> <li key="2016">Villanova</li> </ul>

现在 React 知道只有带着 '2014' key 的元素是新元素,带着 '2015' 以及 '2016' key 的元素仅仅移动了。这样就使得之前的低效变得高效

Tips:

当使用数组下标作为key时:那么修改顺序时会修改当前的 key,导致非受控组件的 state(比如输入框)可能相互篡改导致无法预期的变动

posted @   小蜗蜗蜗牛^o^  阅读(43)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示
CONTENTS