Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

redux实现 #33

Closed
caoxinhui opened this issue May 19, 2020 · 0 comments
Closed

redux实现 #33

caoxinhui opened this issue May 19, 2020 · 0 comments
Labels

Comments

@caoxinhui
Copy link
Owner

caoxinhui commented May 19, 2020

redux做的性能优化

react 数据流和渲染机制

Context api 导致的 re-render

All consumers that are descendants of a Provider will re-render whenever the Provider's value prop changes.

children 相关的 re-render 机制

组件内渲染 this.props.children 不 re-render

性能优化实现

  1. 每次 store 变动,都会触发根组件 setState 从而导致 re-render。我们知道当父组件 re-render 后一定会导致子组件 re-render 。然而,引入 react-redux 并没有这个副作用,这是如何处理的?
    其实在 react-redux v6 中,需要关心这个问题,在 v6 中,每次 store 的变化会触发根组件的 re-render。但是根组件的子组件不应该 re-render。其实是用到了我们上文中提到的 this.props.children。避免了子组件 re-render。在 v7 中,其实不存在该问题,store 中值的变化不会触发根组件 Provider 的 re-render。

  2. 不同的子组件,需要的只是 store 上的一部分数据,如何在 store 发生变化后,仅仅影响那些用到 store 变化部分 state 的组件?

redux 状态管理

redux原理原文链接

状态值 只有 count 值

// 修改count值后,使用count的地方都能收到通知。使用发布-订阅模式
let state = {
    count: 1
}

let listeners = []

function subscribe(listener){
    listeners.push(listener)
}

function changeCount(count) {
    state.count = count
    for (let i = 0; i < listeners.length; i++) {
        const listener = listeners[i]
        listener()
    }
}

subscribe(() => {
    console.log(state.count)
})

changeCount(2)
changeCount(3)
changeCount(4)

将 count 值调整为 initState

const createStore = function(initState) {
    let state = initState
    let listeners = []

    function subscribe(listener) {
        listeners.push(listener)
    }

    function changeState(newState) {
        state = newState
        for (let i = 0; i < listeners.length; i++) {
            const listener = listeners[i]
            listener()
        }
    }

    function getState() {
        return state
    }
    return {
        getState,
        changeState,
        subscribe
    }
}

对状态约束,只允许通过 action 操作。(明确改动范围)

function plan(state, action) {
    switch (action.type) {
        case 'INCREMENT':
            return {
                ...state,
                count: state.count + 1
            }
            case 'DECREMENT':
                return {
                    ...state,
                    count: state.count - 1
                }
                default:
                    return state
    }
}

const createStore = function(plan, initState) {
    let state = initState
    let listeners = []

    function subscribe(listener) {
        listeners.push(listener)
    }

    function changeState(action) {
        state = plan(state, action)
        for (let i = 0; i < listeners.length; i++) {
            const listener = listeners[i]
            listener()
        }
    }

    function getState() {
        return state
    }
    return {
        subscribe,
        getState,
        changeState
    }
}

使用

let initState = {
    count: 0
}
let store = createStore(plan, initState)
store.subscribe(() => {
    let state = store.getState()
    console.log(state.count)
})
store.changeState({
    type: 'INCREMENT'
})
store.changeState({
    type: 'DECREMENT'
})

多文件协作

let state = {
    counter: {
        count: 0
    },
    info: {
        name: '',
        description: ''
    }
}

function counterReducer(state, action) {
    switch (action.type) {
        case 'INCRE':
            return {
                count: state.count + 1
            }
        case 'DECRE':
            return {
                count: state.count - 1
            }
        default:
            return count
    }
}

function InfoReducer(state, action) {
    switch (action.type) {
        case 'SET_NAME':
            return {
                ...state,
                name: action.name
            }
        case 'SET_DESCRIPTION':
            return {
                ...state,
                description: action.description
            }
        default:
            return state
    }
}

const reducers = combineReducers({
    counter: counterReducer,
    info: InfoReducer
})

function combineReducers(reducers) {
    const reducerKeys = Object.keys(reducers)
    return function combination(state, actions) {
        const nextState = {}
        for (let i = 0; i < reducerKeys.length; i++) {
            const key = reducerKeys[i]
            const reducer = reducers[key]
            const previousState = state[key]
            const nextStateForKey = reducer(previousState, actions)
            nextState[key] = nextStateForKey
            state[key] = nextStateForKey
        }
        return nextState
    }
}

let listeners = []

function subscribe(listener) {
    listeners.push(listener)
}
subscribe(() => {
    console.log(state)
})


function changeCount() {
    const newState = reducers(state, {type: 'INCRE'})
    for (let i = 0; i < listeners.length; i++) {
        listeners[i]()
    }
}

changeCount()

使用

const reducer = combineReducers({
    counter: counterReducer,
    info: InfoReducer
})
let initState = {
    counter: {
        count: 0
    },
    info: {
        name: '',
        description: ""
    }
}
let store = createStore(reducer, initState)
store.subscribe(() => {
    let state = store.getState()
    console.log(state.counter.count, state.info.name, state.info.description)
})
// 这里 dispatch 同前面 changeState
store.dispatch({
    type: 'INCREMENT'
})
store.dispatch({
    type: 'SET_NAME',
    name: ''
})

state 拆分与合并

let initState = {
    count: 0
}

function countReducer(state, action) {
    if (!state) {
        state = initState
    }
    switch (action.type) {
        case 'INCREMENT':
            return {
                count: state.count + 1
            }
            default:
                return state
    }
}

const createStore = function(reducer, initState) {
    let state = initState
    let listeners = []

    function subscribe(listener) {
        listeners.push(listener)
    }

    function dispatch(action) {
        state = reducer(state, action)
        for (let i = 0; i < listeners.length; i++) {
            const listener = listeners[i]
            listener()
        }
    }

    function getState() {
        return state
    }
    dispatch({
        type: Symbol()
    })
    return {
        subscribe,
        dispatch,
        getState
    }
}

中间件 middleware

中间件增强 dispatch 的功能

createStore(reducers[,initialState])
reducer(previousState,action)=>newState

const createStore = function (reducer, initState) {
    let state = initState
    let listeners = []

    function subscribe(listener) {
        listeners.push(listener)
    }

    function dispatch(action) {
        state = reducer(state, action)
        for (let i = 0; i < listeners.length; i++) {
            listeners[i]()
        }
    }

    function getState() {
        return state
    }

    dispatch({type: Symbol()})

    return {
        subscribe,
        dispatch,
        getState
    }
}
let state = {

    count: 0

}


function counterReducer(state, action) {
    switch (action.type) {
        case 'INCRE':
            return {
                count: state.count + 1
            }
        case 'DECRE':
            return {
                count: state.count - 1
            }
        default:
            return state
    }
}

const loggerMiddleware = (action) => {
    console.log('this state', store.getState());
    console.log('action', action);
    next(action);
    console.log('next state', store.getState());
}

const exceptionMiddleware = (next) => (action) => {
    try {
        next(action)
    } catch (e) {
        console.error(e)
    }
}
const store = createStore(counterReducer, state)
const next = store.dispatch

store.dispatch = exceptionMiddleware(loggerMiddleware(next))

store.dispatch({
    type: 'INCRE'
})

实现 applyMiddleware

const applyMiddleware = function (...middlewares) {
    return function rewriteCreateStoreFunc(oldCreateStore) {
        return function newCreateStore(reducer, initState) {
            const store = oldCreateStore(reducer, initState)
            const chain = middlewares.map(middleware => middleware(store))
            let dispatch = store.dispatch
            chain.reverse().map(middleware => dispatch = middleware(dispatch))
            store.dispatch = dispatch
            return store
        }
    }
}

react-imvc 状态管理

const createStore = function (reducer, initState) {
    let state = initState
    let listeners = []

    function subscribe(listener) {
        listeners.push(listener)
    }

    function dispatch(action) {
        state = reducer(state, action)
        for (let i = 0; i < listeners.length; i++) {
            listeners[i]()
        }
    }

    function getState() {
        return state
    }

    dispatch({type: Symbol()})
    subscribe((data) => {
        dispatch({
            type: data.actionType,
            payload: data.actionPayload
        })
    })
    return {
        subscribe,
        dispatch,
        getState
    }
}
let state = {
    count: 0
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant