React 实现热门搜索换页功能案例

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
  }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值