来自React文档,基础知识的盲点记录
2020-7-9 更新
- 增加React
API
功能说明、生命周期; - 其他说明内容调整;
核心概念
核心基础知识。
标记:
- 所有内联函数的定义,都会导致组件重新渲染(在更新时渲染两次)。可以通过绑定函数的方式避免。
JSX
ReactDom
使用小驼峰来定义标签的属性名称,比如className
、onClick
etc.ReactDom
对所有输入的内容渲染到页面时,会进行转移,即可防止XSS
攻击。- JSX表达式最好使用
()
包裹,避免遇到自动插入分号陷阱。 ReactDom.render()
用于渲染组件到dom中; 可以多次使用,- JSX语法是
React.createElement(component,props,...children)
语法糖。let myComponent = React.createElement( 'MyComponent', {info:{name:"admin"}}, );
false/null/undefined/true
都不会被渲染,他们可以作为表达式去决定渲染哪个UI。
组件
包括函数组件function
、ES6的class
语法。
-
自定义组件名称必须大写开头,区分原生HTML的标签。
-
setState()
更新可能会是异步的(在组件中批量更新数据操作,会合并后进行更新)。 -
setState()
可以接收一个回调函数,函数参数:preState
、props
. 可使用之前state
的值。this.setState((preState,props)=>({ name:preState.lastName+props.firstName }));
-
setState()
更新会合并原来的state
对象,浅合并;覆盖原有的对象。 -
渲染列表的
key
可以不是全局唯一;但必须是兄弟间唯一。 -
受控组件 - 控制原生HTML表单元素的用户输入,以
React
数据绑定的方式控制取值。 -
组件的数据流向是单向的,可以通过父组件传递回调函数的方式,在子组件属性发生变化时,调用
props.callback
传递数据到父组件。
组件复用、继承
根据业务分割组件,嵌套渲染层级过多,考虑组件分割。
-
自定义组件插槽(slot),
props.children
进行渲染。<MyComponent user = {this.state.userInfo}> <img src={this.state.userInfo.avatar}> </MyComponent> // MyComponent.js render(){ return ( <div> {this.props.children} </div> ) }
-
可将组件作为
props
属性传入到组件中。<MyComponent user={<UserInfo info={this.state.info} />} /> // MyComponent.js render(){ return ( <div> {this.props.user} </div> ) }
-
组合就是将多个单功能组件合并完成一项整体功能。
-
React.lazy()
懒加载指定的组件。减小打包体积,优化加载;React.Suspense
指定加载器,在组件未具备渲染条件。let MyComponent = React.lazy(()=>import("./MyComponent.js")); return (<React.Suspense> <MyComponent /> </React.Suspense>);
高级概念
-
代码分割:减小打包的体积,初始时加载必要的信息;懒加载其他动态导入的模块。
// import 动态导入模块中使用的组件 import("lodash").then(({isEqual,isEmpty})=>{ //... console.log(isEmpty({})); }); // React.lazy 动态导入需要的组件,支持默认导出 const MyComponent = React.lazy(()=>import("./MyComponent.js"));
使用webpack 开发项目时,代码分割参考打包工具 webpack 的配置。
-
Context
用于无需给每层添加props
,在组件间进行数据共享。可查看此文查看Context具体使用// 创建 let MyContext = React.createContext(defaultValue); // 父组件中使用 return (<MyContext.Provider value="admin"> <ChildComponent /> </MyContext.Provider>) // 子组件中使用 ChildComponent.contextType = MyContext; return (<div> <p>{this.context}</p> </div>)
-
错误边界处理,捕获组件中发生的错误渲染备用UI。
static getDerivedStateFromError()
用于渲染备用UI;componentDidCatch()
用于打印错误信息。未作处理时,则会导致整个项目奔溃。
-
refs
提供给我们访问元素DOM节点的方式。// 创建 this.myRef = React.createRef(null); // 使用 , 通过this.myRef.current 访问到 p dom 节点 return (<div> <p ref={this.myRef}></p> </div>)
可以用于
class
组件,获取实例;函数组件没有实例,可通过回调的方式这里有一个列子 -
refs
转发,将子组件的需要访问的DOM元素暴露出来。通过forwardRef((props,ref)=>{})
转发// 父组件 this.myRef = React.createRef(null); return (<div> <ChildComponet ref={this.myRef} /> </div>) // 转发 ref 到目标元素 const ChildComponent = React.forwardRef((props,ref)=>( <button ref={ref}>{props.name}</button> ));
不做转发时,
ref
指向的就是子组件的示例。需要注意的是,如果要隔层传递,每层都需要
forwardRef
转发,ref
属性不作为props
属性传递;也可自定义ref名称,在目标元素使用ref
绑定 -
React.Fragment
用于在无需额外节点时,使用包裹子元素。短语法
标识也可达到目的。return (<> <li>1</li> <>)
React.Fragment
支持传入key 属性。 -
高阶组件(HOC)用于复用组件逻辑的一种技巧。将传入的组件附加其他特性,输出另一个组件。
-
render props
用于在组件之间共享一个值为函数的props技术。解决在组件渲染的UI受父组件某些属性的影响的问题。// 父组件 return (<div> {this.state.data.map(item=> <Child status={(status)=> <Status />} info={item} />)} </div>)
-
Props-Types
做类型检查。import PropTypes from 'prop-types'; MyComponent.propTypes = { render:PropTypes.func.isRequired }
-
非受控组件:除了可受控组件,还有无法做到受控的表单元素。比如:文件输入
input[type='file']
. 所有非受控组件可通过ref
属性访问元素DOM ,获取节点输入值。 -
Portals
用于渲染UI父组件之外 。ReactDom.createPortal(component,dom)
接受一个react组件挂载到指定的DOM元素上。// 可形成类似结构 <body> <div id="root"></div> <div id="portals-root"></div> </body
虽然不是真正意义上的父子组件关系,但在react中可以捕获到来自portal冒泡上来的事件。
可用于对话框、提示框等。
API
React.PureComponent
不同于React.Component
,PureComponent
以浅层对比props
和state
实现了shouldComponentUpdate()
函数。
仅当数据结构比较简单时使用,可以减少了组件的重复更新;如果数据结构层次深、复杂,则需要使用forceUpdate()
强制更新。React.memo()
高阶组件,类似PureComponent
,但只适用于函数组件,检查对比props
变化。接受第二个参数,自定义对比。React.memo(function MyComponent(props){ // 组件 },function propsEqual(prevProps,props){ // 自定义对比 // 如果对比一致则返回 true;不一致返回 false。 });
不同于
shouldComponentUpdate()
对比不同时返回true
标识更新;相同时true
标识需要更新。React.cloneElement
克隆一个新的React元素,返回的React元素新props与旧props浅合并;新的子元素会替代旧子元素;会保留原始元素的key
和ref
.React.isValidElement()
验证元素是否是React元素。React.Children
用于处理this.props.children
数据结构的方法。.map
遍历children
,每个元素调用回调函数;返回数组,如果是null/undefined
则不会返回数组,如果元素是Fragment
不会被遍历。forEach
遍历,无返回;count
总数;only
验证是否只有一个子元素;如果不是则会跑出错误。toArray
以数组的方式扁平化children
,
声明周期
按照组件实例创建执行顺序:
周期 | 函数 | 释义 |
---|---|---|
挂载 | constructor() | 构造函数 |
static getDerivedStateFromProps(props,state) | 返回一个对象来更新state,处理一些由props决定的state值 | |
render() | class组件必须实现的函数,生成DOM | |
componentDidMount() | 组件挂载后调用。 | |
更新 | static getDerivedStateFromProps | |
shouldComponentUpdate(nextProps,nextState) | 手动比较props,state,决定是否需要更新 | |
render() | ||
getSnapshotBeforeUpdate() | 渲染之前调用,返回某些值,将会传入下一个执行的周期函数 | |
componentDidUpdate(prevProps,prevState,snapshot) | 组件更新后调用 | |
卸载 | componentWillUnmount() | 组件卸载或销毁之前调用 |
过时的生命周期componentWillMount()/componentWillReceiveProps()/componentWillUpdate()
,过时的原因说是在异步渲染中,被滥用,出现的问题更多。
Hooks
针对函数式组件提供使用React特性的特性。