React状态管理与路由

240 阅读2分钟

3、Redux

在Redux上解构了Action和Dispatcher

export default addTodo(text) {
    return {
        type: ActionTypes.ADD,
        text: text
    }
}
let action = {
    type: 'add'
}
dispatcher.dispatch(action)
dispatcher.register((action) => {
    switch(action.type) {
        case 'add':
            ...
            break;
    }
})
  • 单一数据源:在redux中,整个应用的全局State,都会保存在一个store中,一个单一数据源store tree 也简化了应用的调试和监控
  • store中的state是只读的:我们不能直接修改store中的state,唯一能改变state的方式就是通过action
  • 使用纯函数来执行修改:接受纯函数来接受action,该纯函数叫reducer,可以改变store中的state

4、Mobx

它通过透明的函数响应式编程使得状态管理变得简单和可扩展,Mobx跟Vue的设计比较相似,是一个响应式状态管理库。Mobx借助于装饰器的实现,使得代码更加简洁易懂。由于使用了可观察对象,所以Mobx可以做到直接修改状态,而不必像Redux一样编写繁琐的actions和reducers

import { observable, compoted } from 'mobx'
class OrderLine {
    @observable price = 0
    @observable amount = 1
    
    @computed get total() {
        return this.price * this.amount
    }
}

5、Recoil

解决的问题:

  • 组件间的状态共享只能通过将state提升至它们的公共祖先来实现,但这样做可以导致重新渲染一颗巨大组件树
  • context只能存储单一值,无法存储多个各自拥有消费者的值的集合
实现一个简易的状态管理工具
export default class CreateStore {
    constructor(reducer, initialState) {
        this.currentReducer = reducer
        this.currentState = initialState
        this.listeners = []
        this.isDispatching = false
    }
    getState() {
        return this.currentState
    }
    subscribe(listener) {
        this.listeners.push(listener)
        return function unsubsribe() {
            var index = this.listeners.indexOf(listener)
            this.listeners.splice(index, 1)
        }
    }
    dispatch(action) {
        try {
            this.isDispatching = true
            this.cunrrentState = currentRudecer(currentState, action)
        } finally {
            this.isDispatching = false
        }
        
        this.listeners.slice().forEach(listener => listener())
        retur
    }
}

React路由与项目实践

React-router-History

History接口允许操作浏览器的曾经在标签页或者框架里访问的会话历史记录

  • MemoryHistory
  • BrowserHistory
  • HasHistory
export interface History {
    readonly action: Action
    readonly location: Location
    createHref(to: To): string
    push(to: To, state?: any): void
    replace(to: To, state?: any): void
    go(delta: number): void
    back(): void
    forward(): void
    listen(listener: Listener): () => void
    block(blocker: Blocker): () => void
}
React-router
  • HasRouter

  • BrowerRouter

  • MemoryRouter

    包裹路由:感知URL变化,提供Provider供嵌套children消费

  • Route

    路由匹配:页面渲染

import React from 'react'
import ReactDom from 'react-dom'
import { BrowserRouter as Router, Route } from 'react-router-dom'ReactDom.render(
    <Router>
        <div>
            <Route exact path='/'>
                <Home />
            </Route>
            <Route path='/news'>
                <News />
            </Route>
        </div>
    </Router>
)

向注入的History注册URL变更监听函数

props

History:暴露封装后的History方法,抹平Hash、History的差异 ------->Router: extend RC,具有react生命周期,监听history变动 -------> ContextProvider ---> ContextConsumer(Route) ----> URL Match ----------> Context

setState setState

Porvider children

路由项目实践
  • 打开任意页面,白屏时间超长:js bundle 资源超大,静态资源超多
  • 一个旁支页面的变更升级,导致主页直接崩溃:一个SPA 应用承载200+页面,巨石应用,变更升级风险极大
  • 页面加载后,数据内容空白时间超长:海量数据接口请求