重学react

183 阅读7分钟

核心库

react、react-dom、react-router-dom、react-redux、redux

脚手架

create-react-app

基础知识

jsx是什么
  • jsx是js的语法糖,可以在js中编写xml,类似xml,可自定义标签;
  • jsx不是HTML,也不是字符串;
  • 标签名要求全部小写;
  • 组件名首字母大写;
  • 他可以配合js表达式一起使用;
  • 所有标签要闭合,哪怕是单标签;
  • jsx中必须有一个顶层包含容器(不想输出标签,可以使用<></>,)
插值表达式是什么

接受的是一个js表达式,运行之后会有一个值的运算就是表达式,如变量、运算和函数调用

不同类型值的表现
  • 字符串、数字,原样输出
  • 布尔值、未定义、空会被忽略
  • 对象,不能在内容里直接输出
  • 数组:字符串拼接输出
条件渲染

|| 、&& 、 ?:

列表渲染

{ list.map((item)=>{}) }

jsx中的特殊属性
  • className、htmlFor、style必须是一个对象:{{}}
  • dangerouslySetHTML,可以让我们设置动态设置元素的 innerHTML
render () {
    return (
      <div
        className='editor-wrapper'
        dangerouslySetInnerHTML={{__html: this.state.innerHTML}} />
    )
  }

组件

在react中,会把视图拆分成若干的组件,如按钮、列表、等等 分为两种:类组件和函数组件

类组件

  • 必须继承自Component或者PureComponent
  • 拥有render方法
组件的视图更新
  • state 状态,通过setState更新状态,会引起组件更新(视图重新渲染)
  • props状态,父组件props改变,子组件重新渲染
事件
  • 注意事件名是小驼峰
  • 事件处理函数的this默认是undefined,可以使用箭头函数或this绑定
setState

setState(updater, [callback])

  • updater: 更新数据 FUNCTION/OBJECT
  • callback: 更新成功后的回调 FUNCTION
  • 异步:react通常会集齐一批需要更新的组件,然后一次性更新来保证渲染的性能
  • 浅合并 Object.assign(),只会修改需要修改的状态
  • 调用setState之后,会触发生命周期,重新渲染组件
  • setState是一个异步方法,调用setState修改状态,并不会立马修改组件的状态,而是进入一个更新流程,在更新过程中修改state 注意:setState是同步还是异步,可参考setState到底是同步还是异步
组件间通信
  1. 父传子 props,单向数据,从上到下
  2. 子传父--函数回调
  3. 兄弟之间 context provider consumer contextType
  4. 第三方库 redux、react-redux、mobx、unstated等等

组件生命周期

挂载阶段
  • constructor(props) --props为父元素传过来的属性
  • static getDerivedStateFromProps --衍生状态,将props中的某些数据关联到状态中-接受props,静态方法是类的方法,不是实例的方法,不需要实例化就可以拿到
  • render--调用render方法,根据render方法的返回值,生成vdom
  • componentDidMount --组件挂载完成,可以获取真实Dom
更新阶段
  • static getDerivedStateFromProps(props)
  • shouldComponentUpdate(nextProps, nextState),如果组件继承自pureComponent,则已经包含了shouldComponentUpdate
  • render()
  • getSnapshotBeforeUpdate(prevProps, prevState),获取更新前的DOM快照,这一步组件即将去更新视图
  • componentDidupdate(prevProps, prevState, preDom),组件更新完成
  • preDom为getSnapshotBeforeUpdate返回的值
卸载阶段

componentWillUnmount() --取消订阅的事件、定时器等等副作用

函数组件

  • 函数组件更新时,是整个函数重新执行
  • return返回我们要构建的视图
  • react 16.7之前没有state和生命周期,16.8开始使用hooks
常用hooks(钩子函数)

const [state, setState] = useState(initstate)

const [状态,修改状态的方法] = useState(初始值)

  • 在同一个组件可以使用多个useState定义多个状态
  • 注意useState返回的setState方法不会进行对象合并
  • 注意useState返回的setState方法同样是异步方法
useEffect**(()=>{},[依赖参数])

处理副作用 DOM操作,异步处理

  1. 没有依赖参数时,每次更新都会执行
  2. []时,挂载完成执行一次
  3. [依赖参数],依赖参数更新时,执行
  4. 卸载时,返回函数,清除副作用
useRef
  • 用户关联原生DOM,或者用来记录组件更新前的数据
  • 当useRef存储的是数据,而非获取DOM或者组件实例时,原数据改变,ref中存储的数据并不会随之改变,需要我们手动改变,通过ref的该特性就可以跨组件的更新阶段传递信息,换句话说,我么可以通过ref来获取组件更新前的信息
hooks使用规则
  • 只能在函数组件中使用
  • 只能在最顶层使用
  • 不能在条件内使用
  • 不能在内部函数使用
hooks优势
  1. 简化组件逻辑
  2. 复用状态逻辑
  3. 无需使用类组件编写

路由-router-单页面应用

分类
  1. HashRouter
  2. BrowserRouter
核心库

react-router-dom

route路由

根据url去匹配不用的视图

  • path默认模糊匹配,即当前url以path开始时,即匹配成功
  • exact:true 精确匹配
  • strict:严格匹配
  • component/render()=>{}/children(三种方式的区别)
route调用视图的三种方式
  1. component 通过组件直接调用
  2. render 接受回调函数,回调函数的返回值中定义该route要渲染的视图
  3. children
其他路由组件
  • Link 本身是处理过的a标签
  • Switch 按照顺序去匹配,匹配成功,则停止匹配
  • NavLink 默认模糊匹配
    • activeClassname=‘link’
    • activeStyle
    • isActive
  • Redirect重定向
路由参数

history

  1. go(n)
  2. goBack(n)
  3. goForward(n)
  4. push(url, state) 不刷新切换路由
  5. length 当前历史记录项长度 location
  6. hash:’’ 当前url的hash值
  7. pathname:’’
  8. search:’’
  9. state: ’‘ push方法传的参数

match-当前路由的匹配信息

  1. isExact
  2. params -动态路由传递的参数
  3. path
  4. url
动态路由

/list/:id

动态路由在定义path时,路由中某一段可能是非固定的值,不能用精确匹配

路由动画库

react-transition-group

非路由导航中,获取路由参数
  • 高阶路由

newCmp = withRouter(cmp),适用于类组件和函数组件

  • router提供的hooks钩子是router 5之后才有的,只能用在函数组件中
  1. useHistory()-获取history对象
  2. useLocation()-获取location对象
  3. useParams()-获取动态路由参数
  4. useRouterMatch()-获取match对象

redux使用

redux是js的状态容器,提供可预测化的状态管理工具

核心api
  1. createStore --可创建store(仓库),
  2. combineReducer --可合并多个reducer,多个reducer中type也不能重名,所以命名最好:reudcer_type,const store = createStore(reducer)
  3. getState --store.getState() 可以获取到当前state
  4. dispatch --store.dispatch({type:’add’}, payload) action的type必写,调用dispatch,store会调用reducer,并把state和action传给reducer
  5. subscribe --监听state改变(订阅),返回一个函数,可用于取消监听
  6. reducer --纯函数,提供操作状态的各种方式,function reducer(state={}, action={}){},接受state,action返回新state
纯函数
  1. 在该函数中,没有任何副作用
  2. 该函数不依赖于外部的环境
  3. 不修改函数的输入值
  4. 相同的输入永远返回相同的输出,不能使用math.random或者请求数据
redux三大原则
  1. 单一数据源:整个应用的state被储存在一个object tree中,并且这个object tree只存在于唯一一个store中
  2. state是只读的:唯一改变的方法就是触发 action,action是一个用于描述已发生事件的普通对象
  3. 使用纯函数来执行修改state

react-redux使用

  • 安装: npm i react-redux redux
  • const store = createStore(reducer)
  • 高阶组件,注入store数据源
  • newCmp = connect(mapStatetoProps,mapDispatchToProps)(cmp)
  • mapStatetoProps = (state)=>{return state}返回该组件需要的state
react-redux 提供的Hooks
  1. useStore()-获取store
  2. useSelector((state)=>{return state})-获取对应state
  3. useDispatch() -获取dispatch
redux-thunk

使action支持函数

  1. 如果action是对象,则直接调用reducer发起状态修改
  2. 如果action是函数,则执行该函数,并将getstate和dispatch传递给该函数,const store = createStore(reducer, applymiddleware(thunk,...多个))
  3. hooks时代可以使用自定义hooks替代中间件,方便简洁,具体就是:方法内获取收据,获取到数据后,再调用dispatch来修改数据

项目结构

App.js
index.js
static-静态资源(图片、css)
src
  component-存放公共组件
  view-视图层
    components-页面级组件
    index.js
    index.module.css
  store-状态仓库
    action
    reducer
    index.js
router.js-路由表
package.json
webpack.config.js

其他

React.StrictMode

严格模式,即将废弃的语法都禁止使用,比如:废弃的will生命周期,refs获取dom等

index.module.css

支持css模块化,避免同名样式相互污染 :local(.local)局部变量 :globle(.public)全局,不进行混淆编译

按需加载处理

使用suspense和lazy进行懒加载设置 1.子组件用到再展示

<Suspense fallback={<div>模块加载中…</div>}>
	<Child>
</Suspense>

2.可以应用于路由,用到路由再加载组件