11.热门搜索中数据换一批功能19-06-14
代码见https://gitee.com/XiaoKunErGe/JianShu.git历史版本第13次提交。
一.首先要让鼠标移到搜索弹出框范围内时,弹出框不隐藏
1.在header下的reducer中,添加一个新的值mouseIn初始值设为false
const defaultState = fromJS({
focused: false,
list:[],
mouseIn:false
});
2.到header下的index中的<SearchInfo/>组件中添加两个方法,既鼠标移入移出的方法
<SearchInfo
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
>
在mapDispatchToProps将事件传给store
constants.js添加代码
export const MOUSE_ENTER = 'header/MOUSE_ENTER';
export const MOUSE_LEAVE = 'header/MOUSE_LEAVE';
actionCreators.js添加代码
export const mouseEnter = () => ({
type: constants.MOUSE_ENTER
});
export const mouseLeave = () => ({
type: constants.MOUSE_LEAVE
});
到reducer中处理事件并将响应事件反应给用户
reducer.js中的代码
case constants.MOUSE_ENTER:
return state.set('mouseIn', true);
case constants.MOUSE_LEAVE:
return state.set('mouseIn', false);
到mapStateToProps中接收mouseIn值并用以限制<SearchInfo/>组件是否显示
mouseIn: state.getIn(['header', 'mouseIn']),
if (focused ||mouseIn ){
return(
<SearchInfo
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
>
<SearchInfoTittle>
热门搜索
<SearchInfoSwitch onClick={()=> handelChangePage(page, totalPage)}>换一批</SearchInfoSwitch>
</SearchInfoTittle>
<SearchInfoList>
{先别管这儿}
</SearchInfoList>
</SearchInfo>
)
}else {
return null;
}
}
二.实现换一批功能
1.到reducer中添加两个值,page(当前显示的页数),totalPage(一共多少页)
const defaultState = fromJS({
focused: false,
list:[],
mouseIn:false,
page: 1,
totalPage:1
});
2.到mapStateToProps处获取page值
page: state.getIn(['header', 'page']),
3.删除之前<SearchInfoItem/>组件的方法,将<SearchInfoItem/>方法拿出来,改写在getListArea()方法下
a. ######在这里拿到list数据,并将其immutable转换成JS类型,因为immutable类型无法使用list[ i ]这种语法取值。
const newList = list.toJS();
b.建一个空数组用来放每页显示的数据
const pageList = [];
c.添加for循环为每一页的Item显示数据
for(let i = (page-1)*10 ;i < page *10 ; i++){
//初始值page不能设置为0,因为 i < page *10,设置为零for循环不走
//10是要求每页显示10个Item
pageList.push(
<SearchInfoItem key={newList[i]}>{newList[i]}</SearchInfoItem>
)
}
这时存在一个问题就是,如果你的数据个数不是10的倍数,运行到最后一组数据时,就会报一个key值不存在的错,这时需要加以判断
if ( page*10 < newList.length ){
//当循环数据数小于数据总量是,也就是不是最后一组数据时循环 (page-1)*10 到 10*page 的数次,既10次
for(let i = (page-1)*10 ;i < page *10 ; i++){
pageList.push(
<SearchInfoItem key={newList[i]}>{newList[i]}</SearchInfoItem>
)
}
}else {
//当循环数据数大于数据总量是,也就是是最后一组数据时循环 (page-1)*10 到 newList.length的数次,既(newList.length - (page-1)*10)次
for(let i = (page-1)*10 ;i < newList.length; i++){
pageList.push(
<SearchInfoItem key={newList[i]}>{newList[i]}</SearchInfoItem>
)
}
}
在SearchInfoList中调用以上方法
<SearchInfoList>
{pageList}
</SearchInfoList>
d.这时运行项目,只显示一组10个数据,因为我们传的page值是固定的只有一个。接下来改变数据,实现‘换一批’功能。
这里要获取总共页数
在action传递list给reducer的代码中(actionCreators的changeList中),添加一个值totalPage
export const changeList = (data) => ({
type: constants.CHANGE_LIST,
data:fromJS(data),
totalPage: Math.ceil(data.length / 10)
//data.length是获取的list值个数,10是每页要求显示多少个,Math.ceil是取整。
});
到reducer中返回数据
case constants.CHANGE_LIST:
return state.set('list', action.data).set('totalPage', action.totalPage);
到index.js中mapStateToProps中接收数据
totalPage: state.getIn(['header', 'totalPage'])
这时在index中就拿到了总共显示的页数。
e.到 ‘换一批’ 组件处添加handelChangePage方法,将page值判断后传给sore
<SearchInfoSwitch onClick={()=> handelChangePage(page, totalPage) }>换一批</SearchInfoSwitch>
在mapDispatchToProps中实现方法
handelChangePage(page, totalPage) {
if (page < totalPage){
dispatch(actionCreators.changePage(page+1))
}else{
//页数大于总页数时显示开始从第一页显示
dispatch(actionCreators.changePage(1))
}
}
到这里就结束了。
整理代码:
export default (state = defaultState, action) => {
switch(action.type) {
case constants.SEARCH_FOCUS:
return state.set('focused', true);
case constants.SEARCH_BLUR:
return state.set('focused', false);
case constants.CHANGE_LIST:
return state.merge({
//merge可以同时改变多个数据内容,相当于多次调用set,比set性能更高
list: action.data,
totalPage: action.totalPage
})
case constants.MOUSE_ENTER:
return state.set('mouseIn', true);
case constants.MOUSE_LEAVE:
return state.set('mouseIn', false);
case constants.CHANGE_PAGE:
return state.set('page', action.page);
default:
return state
}
};
注意:不要忘了要把所有接收的数据和方法都添加在this.props里
const { focused,mouseIn,list,page,totalPage,handelChangePage,handleMouseEnter,handleMouseLeave } = this.props;