React 是一个声明式,高效且灵活的用于构建用户界面的 JavaScript 库。
官网。
JSX
React 中一般用 JSX 输出 UI。JSX 可以简单的理解为,包含 JavaScript 表达式的 HTML 。
function formatName(user) {return user.firstName + ' ' + user.lastName;}const user = {firstName: 'Harper',lastName: 'Perez'};const element = (<h1>Hello, {formatName(user)}!</h1>);ReactDOM.render(element,document.getElementById('root'));
渲染列表
item 上一定要加 key。不要用数组的下标做为 Key。用数组的下标做为 Key 会有性能问题。
<ul>{list.map(item =>(<li key={item.id>{item.name}</li>)}</ul>
条件渲染
{isShow && <div>...</div>}<b>{isLoggedIn ? 'currently' : 'not'}</b>
一个组件返回多个元素
render() {return (<React.Fragment><ChildA /><ChildB /><ChildC /></React.Fragment>);}
简写
render() {return (<><ChildA /><ChildB /><ChildC /></>);}
事件
绑定事件
React 元素的事件处理和 DOM 元素的很相似,但是有一点语法上的不同:
- React 事件的命名采用小驼峰式(camelCase),而不是纯小写。
- 使用 JSX 语法时你需要传入一个函数作为事件处理函数,而不是一个字符串。
<button onClick={activateLasers}>Activate Lasers</button>
回调中获取事件对象 & 传额外参数
<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
停止冒泡到原生的事件
<div onClick={e => e.nativeEvent.stopImmediatePropagation()}>...</div>
类组件
组件 API
setState(changeState, cb)
大部分情况是异步的。
生命周期

render()
返回要渲染的元素。
constructor
主要用来设置 state 的初始值。
constructor(props) {super(props);// 不要在这里调用 this.setState()this.state = { counter: 0 };this.handleClick = this.handleClick.bind(this);}
componentDidMount()
DOM 加载好后会被调用。通常放下面的操作:
- 依赖于 DOM 节点的初始化操作。
- 接口调用。
componentDidUpdate(prevProps, prevState, snapshot)
组件更新后会被调用。通常放下面的操作:
- 监控 props 或 state 的变化。
- 对 DOM 进行额外的操作。
注意: componentDidUpdate() 中直接调用 setState() 必须被包裹在一个条件语句里,否则会导致死循环。componentDidUpdate(prevProps) {// 典型用法(不要忘记比较 props):if (this.props.userID !== prevProps.userID) {this.fetchData(this.props.userID);}}
componentWillUnmount()
componentWillUnmount() 会在组件卸载及销毁之前直接调用。在此方法中执行必要的清理操作,例如,清除 timer,取消网络请求或清除在 componentDidMount() 中创建的订阅等。
函数组件
Hook API
useState
存数据。
import React, { useState } from 'react';function Example() {// 声明一个叫 "count" 的 state 变量const [count, setCount] = useState(0);return (<div><p>You clicked {count} times</p><button onClick={() => setCount(count + 1)}>Click me</button></div>);}
useContext
const ctx = React.createContext()const { Provider, Consumer } = ctx<Provider value={{name: 'joel'}}><Child /></Provider>function Child() {const nameCtx = useContext(ctx)return <div>{nameCtx.name}</div>}
useEffect
执行副作用。
useEffect(() => {fetchInitData()window.addEventListener('mouseup', handleStopResizing);return () => {window.removeEventListener('mouseup', handleStopResizing);};}, [])useEffect(() => {fetchDetail(id)}, [id])
useLayoutEffect
在所有的 DOM 变更之后同步调用 effect。可以使用它来读取 DOM 布局并同步触发重渲染。
useCallback
给子组件传函数类型的属性,要用 useCallback。
const handleClick = useCallback(() => {}, [...])return (<Sub onClick={handleClick} />)
组件间通信
父子
父给子传参
props。
子通知父
调用 props 的函数。
父主动让子做些事
方案1: 主动调用。用 refs。
方案2: 子监控父组件的属性。
兄弟
共用数据的改变
状态提升。
祖先和子
祖先给子传参
方案1: 一层层往下传。
方案2: Context API。
类组件:
const ctx = React.createContext()const { Provider, Consumer } = ctx<Provider value={{name: 'joel'}}><Consumer>{ctx => ( // Provider 上 value 属性的值<Component{...props}name={ctx.name}/>)}</Consumer></Provider>
函数组件
const ctx = React.createContext()const { Provider, Consumer } = ctx<Provider value={{name: 'joel'}}><Child /></Provider>function Child() {const nameCtx = useContext(ctx)return <div>{nameCtx.name}</div>}
祖先让子做些事
方案1: 主动调用。用 forwoardRef。
方案2: 子监控祖先组件的属性。
组件复用
单一职责
UI 和 逻辑的分离。对应的是展示组件 和 容器组件。
多组件共用数据的分离。将数据和对数据操作的放在一起。
高阶组件(HOC)
// 定义function withName (Component) {return (props) => <Component {...props} name="Joel"/>}// 使用。用装饰器看起来更舒服。const WithNameComp = withName(Comp)
Render Props
// 定义function Provider (props) {return <div>{props.children({name: 'Joel', ...props})}</div>}// 使用<Provider>{(props) => {return <Comp name={props.name}/>}}</Provider>
Use Hooks
// 定义import { useState, useEffect } from 'react';function useFriendStatus(friendID) {const [isOnline, setIsOnline] = useState(null);useEffect(() => {function handleStatusChange(status) {setIsOnline(status.isOnline);}ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange);return () => {ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange);};});return isOnline;}// 使用function FriendListItem(props) {const isOnline = useFriendStatus(props.friend.id)}
