美文网首页
11.项目实战:Header组件开发(三)

11.项目实战:Header组件开发(三)

作者: 小二的学习日记 | 来源:发表于2020-07-19 11:27 被阅读0次

使用React-Redux进行应用数据的管理

我们想引入Redux进行数据管理,顺便把之前的focused也放进去。
1.首先导入redux相关的两个模块
cnpm install --save redux react-redux
2.编写redux的一些基础文件

//===>src/store/index.js
import { createStore } from 'redux'
import reducer from './reducer'

const store = createStore(reducer)
export default store
//===>src/reducer.js
const defaultState = {
    focused: false
}

export default (state = defaultState, action) => {
    if (action.type === 'search_focus') {
        return {
            focused: true
        }
    }
    if (action.type === 'search_blur') {
        return {
            focused: false
        }
    }
    return state
}

3.修改Header组件,把之前focused放到redux中进行管理

//===>src/common/header/index.js
import React, { Fragment } from 'react'
import { CSSTransition } from 'react-transition-group'
import {
    HeaderWrapper,
    Logo,
    Nav,
    NavItem,
    SearchWrapper,
    NavSearch,
    Addition,
    Button
} from './style'
import { IconFontStyle } from '../../statics/iconfont/iconfont';
import { connect } from 'react-redux'

const Header = (props) => {
    return (
        <Fragment>
            <IconFontStyle />
            <HeaderWrapper>
                <Logo />
                <Nav>
                    <NavItem className='left'>首页</NavItem>
                    <NavItem className='left'>下载App</NavItem>
                    <NavItem className='right'>登录</NavItem>
                    <NavItem className='right'>
                        <span className="iconfont">&#xe636;</span>
                    </NavItem>
                    <SearchWrapper>
                        <CSSTransition
                            in={props.focused}
                            timeout={200}
                            classNames="slide">
                            <NavSearch
                                className={props.focused ? 'focused' : ''}
                                onFocus={props.handleInputFocus}
                                onBlur={props.handleInputBlur}>
                            </NavSearch>
                        </CSSTransition>
                        <span className={props.focused ? 'focused iconfont' : 'iconfont'}>&#xe662;</span>
                    </SearchWrapper>
                    <Addition>
                        <Button className='writting'>
                            <span className="iconfont">&#xe6e5;</span>写文章
                        </Button>
                        <Button className='reg'>注册</Button>
                    </Addition>
                </Nav>
            </HeaderWrapper>
        </Fragment>
    )
}

const mapStateToProps = (state) => {
    return {
        focused: state.focused
    }
}
const mapDispatchToProps = (dispatch) => {
    return {
        handleInputFocus() {
            const action = {
                type: 'search_focus'
            }
            dispatch(action)
        },
        handleInputBlur() {
            const action = {
                type: 'search_blur'
            }
            dispatch(action)
        }
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(Header)

效果不变。

使用combineReducers完成对数据的拆分管理

首先我们先用redux-devtools-extension去做下监控

//===>src/store/index.js
import { createStore, compose } from 'redux'
import reducer from './reducer'

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(reducer, composeEnhancers());
export default store

我们想把reducer对组件们的操作,拆分到每一个组件对应的文件夹中。
1.新建header组件的reducer文件

//===>src/common/header/store/index.js
import reducer from './reducer'
export { reducer }
//===>src/common/header/store/reducer.js
const defaultState = {
    focused: false
}

export default (state = defaultState, action) => {
    if (action.type === 'search_focus') {
        return {
            focused: true
        }
    }
    if (action.type === 'search_blur') {
        return {
            focused: false
        }
    }
    return state
}

2.用store把他们管理起来

//===>src/store/reducer.js
import { combineReducers } from 'redux'
import {reducer as headerReducer} from '../common/header/store'

const reducer = combineReducers({
    header: headerReducer
})

export default reducer

3.最后,千万不要忘记,我们把数据拆分了,那要改一下组件中找属性的路径

//===>src/common/header/index.js
...
const mapStateToProps = (state) => {
    return {
        focused: state.header.focused
    }
}
...

actionCreators与constants的拆分

这一小节,我们的目标是,整理header的store。
任务一:在header文件夹下的store中,暴露出store相关的内容,以便Header组件只引入store的index.js就可以解构出reducer、constants等内容。

//===>src/common/header/store/index.js
import reducer from './reducer'
import * as actionCreators from './actionCreators'
import * as constants from './constants'

export { reducer, actionCreators, constants }

任务二:创建actionCreators并使用。
1.编写全局变量

//===>src/common/header/store/constants.js
export const SEARCH_FOCUS = 'header/SEARCH_FOCUS'
export const SEARCH_BLUR = 'header/SEARCH_BLUR'

2.编写actionCreators

//===>src/common/header/store/actionCreators.js
import *  as constants from './constants'

export const searchFocus = () => ({
    type: constants.SEARCH_FOCUS
})

export const searchBlur = () => ({
    type: constants.SEARCH_BLUR
})

3.修改header的reducer,引入刚才定义的全局变量

//===>src/common/header/store/reducer.js
import *  as constants from './constants'

const defaultState = {
    focused: false
}

export default (state = defaultState, action) => {
    if (action.type === constants.SEARCH_FOCUS) {
        return {
            focused: true
        }
    }
    if (action.type === constants.SEARCH_BLUR) {
        return {
            focused: false
        }
    }
    return state
}

4.在Header组件中修改action的分发

import { actionCreators } from './store';
...
const mapDispatchToProps = (dispatch) => {
    return {
        handleInputFocus() {
            dispatch(actionCreators.searchFocus())
        },
        handleInputBlur() {
            dispatch(actionCreators.searchBlur())
        }
    }
}
...

使用Immutable.js来管理store中的数据

在reducer中,我们不希望修改state的数据,而是希望返回一个新的数据。所以我们引入了Immutable
1.引入第三方模块Immutable
npm install --save immutable
2.修改reducer,把state包装成immutable类型
immutable对象的set方法,会结合之前的immediate对象的值和设置的值,返回一个全新的对象。

//===>src/common/header/store/reducer.js
import *  as constants from './constants'
import { fromJS } from 'immutable'

const defaultState = fromJS({
    focused: false
})

export default (state = defaultState, action) => {
    if (action.type === constants.SEARCH_FOCUS) {
        return state.set('focused', true)
    }
    if (action.type === constants.SEARCH_BLUR) {
        return state.set('focused', false)
    }
    return state
}

3.因为state.header已经是immutable类型的量了,我们就不能用传统方法去改变他的值了。

//===>src/common/header/index.js
...
const mapStateToProps = (state) => {
    return {
        focused: state.header.get('focused')
    }
}
...

这样就可以了。

使用redux-immutable统一数据格式

上一小节中,第三步focused: state.header.get('focused') 这个写法很奇怪,state对象是个普通js对象,但state.header却是一个immutable对下对象。这一小节的我们的目标是,把state统一成immutable对象。
1.导入redux-immutable
npm install --save redux-immutable
2.修改combineReducers的引入

//===>src/store/reducer.js
//import { combineReducers } from 'redux'  把这个改成下面这个,它里面的state就变成immutable类型的对象了。
import { combineReducers } from 'redux-immutable'
...

3.因为state已经是immutable类型的量了,我们就不能用传统方法去改变他的值了。

//===>src/common/header/index.js
...
const mapStateToProps = (state) => {
    return {
        // focused: state.get('header').get('focused')
        focused: state.getIn(['header', 'focused'])
    }
}
...

相关文章

网友评论

      本文标题:11.项目实战:Header组件开发(三)

      本文链接:https://www.haomeiwen.com/subject/wglfkktx.html