1. header > index.js组件部分代码
import React, { Component } from "react";
import { connect } from 'react-redux';
import { CSSTransition } from "react-transition-group";
import { HeaderWrapper, Logo, Nav, NavItem, NavSearch, Addition, Button, SearchWrapper, SearchInfo, SearchInfoTitle, SearchInfoSwitch, SearchInfoItem, SearchInfoList } from "./style";
import { getFocusAction, getBlurAction, getList, mouseEnterAction, mouseLeaveAction, changePageAction } from './store/actionCreators'
class Header extends Component {
getListArea() {
const { focused, list, page, totalPage, mouseIn, handleMouseEnter, handleMouseLeave, handleChangePage } = this.props;
const newList = list.toJS();//immu table数组转普通数组
const pageList = [];
//如果一开始初始化时,并没有发ajax请求,数据不存在就不做循环
if (newList.length) {
for (let i = (page - 1) * 10; i < page * 10; i++) {
//page为1时候,显示[0]-[9]项,以此类推
pageList.push(
<SearchInfoItem key={newList[i]}>{newList[i]}</SearchInfoItem>
)
}
}
if (focused || mouseIn) {
return (
<SearchInfo
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}>
<SearchInfoTitle>
热门搜索
<SearchInfoSwitch
onClick={() => handleChangePage(page, totalPage)}>换一批</SearchInfoSwitch>
</SearchInfoTitle>
<SearchInfoList>
{pageList}
</SearchInfoList>
</SearchInfo>
)
} else {
return null;//什么都不返回
}
}
render() {
const { focused, handleInputFocus, handleInputBlur } = this.props
return (
<HeaderWrapper>
<Logo />
<Nav>
...
{this.getListArea()}
...
</Nav>
</HeaderWrapper>
)
}
}
const mapStateToProps = (state) => {
return {
//focused: state.focused 没用immutable时
focused: state.getIn(['header', 'focused']),//也可写为 state.get('header').get('focused')
list: state.getIn(['header', 'list']),
page: state.getIn(['header', 'page']),
totalPage: state.getIn(['header', 'totalPage']),
mouseIn: state.getIn(['header', 'mouseIn'])
}
}
const mapDispatchToProps = (dispatch) => {
return {
handleInputFocus() {
//改变focused数据的值变为true 作用是控制search框的显示和input框的长短
dispatch(getFocusAction());
//redux-thunk使得我们可以去action里做异步操作 请求search的数据
dispatch(getList());
},
handleInputBlur() {
dispatch(getBlurAction());
},
handleMouseEnter() {
dispatch(mouseEnterAction());
},
handleMouseLeave() {
dispatch(mouseLeaveAction());
},
//换页,在组件中决定传第几页的值
handleChangePage(page, totalPage) {
if (page < totalPage) {
//如果当前页码小于总页码,点击换一换就加一页
dispatch(changePageAction(page + 1));
} else {
//如果当前页码为最后一页,就回到第一页
dispatch(changePageAction(1));
}
}
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Header);
2. header > store > actionCreators.js
import { search_focus, search_blur, change_list, mouse_enter, mouse_leave, change_page } from "./actionTypes";
import { fromJS } from 'immutable';
import axios from "axios"
//换页
export const changePageAction = (page) => ({
type: change_page,
page
})
//因为reducer中的list在最外层包裹了fromJS,最初list数组就已经被变成了immutable类型的数组
//因此要在这里做统一
const changeListAction = (data) => ({
type: change_list,
data: fromJS(data),
totalPage: Math.ceil(data.length / 10)//向上取整
})
//因为用了redux-thunk,函数返回函数,这也是thunk的意义
export const getList = () => {
return (dispatch) => {
//请求假数据 来自public > api > headerList.json
axios.get('/api/headerList.json').then((res) => {
const data = res.data;
const action = changeListAction(data.data)//将list中的内容传给此函数
dispatch(action)
}).catch(() => {
console.log("error");
})
}
}
3. header > store > reducer.js
import { search_focus, search_blur, change_list, mouse_enter, mouse_leave, change_page } from "./actionTypes";
import { fromJS } from 'immutable'
const defaultState = fromJS({
focused: false,
mouseIn: false,
list: [],
page: 1,
totalPage: 1
});
export default (state = defaultState, action) => {
switch (action.type) {
case search_focus:
return state.set('focused', true);
case search_blur:
return state.set('focused', false);
//immutable时,merge相当于多次调用set,性能更高
case change_list:
return state.merge({
list: action.data,
totalPage: action.totalPage
})
case mouse_enter:
return state.set('mouseIn', true);
case mouse_leave:
return state.set('mouseIn', false);
case change_page:
return state.set('page', action.page);
default:
return state
}
}