函数组件
class 组件只接受一个 props ,没有其他逻辑,可以使用函数组件
- 纯函数,输入 props ,输出 JSX
- 没有实例,没有生命周期,没有 state
- 不能扩展其他方法
非受控组件(相对于受控组件)
- ref
- input 的值不受 state 的控制,只是赋了个默认的初始值 ```jsx import React, { LegacyRef } from “react”;
interface Props {}
interface StateType { count: number; name: string; }
export class Header extends React.Component
this.state = {count: 0,name: "jesse",};this.nameRef = React.createRef();this.handleClick = this.handleClick.bind(this);
}
handleClick() { const elem = this.nameRef.current; console.log(elem.value); }
render() { const { name } = this.state; return (
{/ 使用 defaultValue ,而不是 value ,使用 ref /}
{/ state 不会随着改变 /}
state.name: {name}
);
}
}
- defaultValue,defaultChecked- 手动操作 DOM 元素使用场景<br />必须要 DOM 操作,setState 实现不了,使用非受控组件<br />文件上传:`<input type="file">`<br />富文本编辑器,需要传入 DOM 元素<a name="5VGKX"></a>#### Portals传送门<br />让组件渲染到父组件之外```jsximport React from "react";import ReactDOM from "react-dom";interface Props {}interface StateType {}export class B extends React.Component<Props, StateType> {constructor(props: Props) {super(props);this.state = {};}render() {return ReactDOM.createPortal(// {this.props.children} 类似于 vue 的 slot<div className="b-modal">{this.props.children}</div>,document.body);}}
使用场景
overflow: hidden- 父组件的
z-index值大小 fixed需要放在body第一层级
context
上下文
import { Button } from "antd";import React from "react";import ReactDOM from "react-dom";interface Props {}interface StateType {theme: string;}const ThemeContext = React.createContext("light");// 函数式组件function ThemeLink(props: Props) {return (<ThemeContext.Consumer>{(value) => <p>link theme is {value}</p>}</ThemeContext.Consumer>);}class ThemeButton extends React.Component {// 写法1:指定 contextTypestatic contextType = ThemeContext;render() {const theme = this.context;return (<div><p>button theme is {theme}</p></div>);}}// 写法2:指定 contextType// ThemeButton.contextType = ThemeContext;function ToolBar(props: Props) {return (<div><ThemeButton /><ThemeLink /></div>);}export class C extends React.Component<Props, StateType> {constructor(props: Props) {super(props);this.state = {theme: "light",};}changeTheme = () => {this.setState({theme: this.state.theme === "light" ? "dark" : "light",});};render() {const { theme } = this.state;return (<ThemeContext.Provider value={theme}><ToolBar /><hr /><Button onClick={this.changeTheme}>change theme</Button></ThemeContext.Provider>);}}
使用场景
- 主题
- 语言
- 认证的用户
异步组件
import()React.lazyReact.Suspence```jsx const C = React.lazy(() => import(“components/header/context”));
<a name="wNhoE"></a>#### 性能优化(对 React 更加重要)- `SCU`react 为什么不内部作对比,而是通过 SCU 去让用户做操作?- 重点:react 默认:父组件更新,子组件无条件更新!- 避免不规范的写法,或者违反了不可变值SCU 一定要每次都用吗?- 需要才优化SCU 默认返回 true , react 默认重新渲染所有组件<br />必须配合不可变值一起使用<br />有性能问题,再考虑使用```jsxshouldComponentUpdate(nextProps: Readonly<Props>,nextStates: Readonly<StateType>): boolean {if (nextStates.theme !== this.state.theme) {// 可以渲染return true;}// 不重复渲染return false;}
PureComponent和React.memo- 纯组件
- SCU 实现浅比较
- 尽量不要做深度比较
React.PureComponent- 函数式组件
React.memo
- 不可变值
[immutable.js](https://immutable-js.com/)
HOC 高阶组件
就是一个函数,接收一个组件作为参数,返回一个新的函数。
工厂模式
模式简单,增加组件层级
import React from "react";interface HOCProps {x: number;y: number;}const withMouse = <P extends HOCProps>(Component: React.ComponentType<P>) => {class HOC extends React.Component {constructor(props: P) {super(props);this.state = { x: 0, y: 0 };}onMouseMove = (event: React.MouseEvent<HTMLDivElement>) => {this.setState({x: event.clientX,y: event.clientY,});};render() {return (<div style={{ height: "100px" }} onMouseMove={this.onMouseMove}>{/* 透传所有 props , 增加 mouse 属性 */}<Component {...(this.props as P)} mouse={this.state} /></div>);}}return HOC;};const Mouse = (props: any) => {const { x, y } = props.mouse;return (<div style={{ height: "100px" }}><h1>x: {x}, y: {y}</h1></div>);};export default withMouse(Mouse);
Render Props
通过一个函数将 class 组件中的 state 作为 props 传递给纯函数式组件
代码简洁,学习成本高
import React from "react";interface State {x: number;y: number;}interface Props {render: (state: State) => JSX.Element}class Mouse extends React.Component<Props, State> {constructor(props: Props) {super(props);this.state = { x: 0, y: 0 };}onMouseMove = (event: React.MouseEvent<HTMLDivElement>) => {this.setState({x: event.clientX,y: event.clientY,});};render() {return (<div style={{ height: "100px" }} onMouseMove={this.onMouseMove}>{/* 将 state 作为 props 传递给 render 函数 */}{this.props.render(this.state)}</div>);}}// Mouse.propTypes = {// render: PropTypes.func.isRequired,// };const Ap = () => (<div style={{ height: "100px" }}><Mouse// render 是一个函数组件render={({ x, y }: State) => (<h1>mouse position is x: {x}, y: {y}</h1>)}/></div>);export default Ap
