19. 项目实战:首页开发(五)

返回顶部功能实现

今天我们要做的是,回到顶部的功能。

image.png

我们通过reducer中showScroll这个属性判断是否显示这个按钮,那什么时候触发showScroll属性的改变呢?我们在生命周期钩子函数挂载组件的时候绑定window的滑动监听事件,卸载前解绑这个事件就可以了。数据的改变我们使用的redux。
1.添加一个用来分发scroll事件的action常量

//===>src/pages/home/store/constants.js
export const CHANGE_HOME_DATA = 'home/CHANGE_HOME_DATA'
export const ADD_ARTICLE_LIST = 'home/ADD_ARTICLE_LIST'
export const TOGGLE_SCROLL_TOP = 'home/TOGGLE_SCROLL_TOP'

2.编写actionCreators.js

//===>src/pages/home/store/actionCreators.js
...
export const toggleTopShow = (show) => ({
    type: constants.TOGGLE_SCROLL_TOP,
    show
})

3.编写reducer.js

import { fromJS } from 'immutable';
import * as constants from './constants'

const defaultState = fromJS({
    topicList: [],
    articleList: [],
    recommendList: [],
    articlePage: 1,
    showScroll: false
});

export default (state = defaultState, action) => {
    switch (action.type) {
        ...
        case constants.TOGGLE_SCROLL_TOP:
            return state.set('showScroll', action.show)
        default:
            return state;
    }
}

4.接下来我们把这个按钮写在Home组件中

//===>src/pages/home/index.js
import React, { Component } from 'react'
import { HomeWrapper, HomeLeft, HomeRight, BackTop } from './style'
import Topic from './components/Topic'
import List from './components/List'
import Recommend from './components/Recommend'
import Writer from './components/Writer'
import { connect } from 'react-redux'
import { actionCreators } from './store'
class Home extends Component {

    handleScrollTop() {
        window.scrollTo(0, 0)
    }

    render() {
        return (
            
                
                    
                    
                    
                
                
                    
                    
                
                {
                    this.props.showScroll ?
                        回到
                        : null
                }
            
        )
    }

    componentDidMount() {
        this.props.changeHomeData()
        this.bindEvents()
    }

    componentWillUnmount() {
        window.removeEventListener('scroll', this.props.changeScrollTop)
    }

    bindEvents() {
        window.addEventListener('scroll', this.props.changeScrollTop)
    }
}
const mapDispatch = (dispatch) => ({
    changeHomeData() {
        const action = actionCreators.getHomeInfo()
        dispatch(action)
    },
    changeScrollTop() {
        if (document.documentElement.scrollTop > 100) {
            dispatch(actionCreators.toggleTopShow(true))
        } else {
            dispatch(actionCreators.toggleTopShow(false))
        }
    }
})

const mapState = (state) => ({
    showScroll: state.getIn(['home', 'showScroll'])
})

export default connect(mapState, mapDispatch)(Home)

5.最后写backTop的样式

//===>src/pages/home/style.js
...
export const BackTop = styled.div`
position:fixed;
right:100px;
bottom:100px;
width:60px;
height:60px;
line-height:60px;
text-align:center;
border:1px solid #ccc;
font-size:14px;
`
我们简单的实现了这个功能

首页性能优化及路由跳转

两个功能
1.点击列表的item,跳转到详情页
2.点击左上角的Logo,返回首页
1.为List组件的item增加路由跳转功能。我们的路由是组件化跳转,不需要url的重新请求,所以用的是react-router-dom三方模块的Link

...
import { Link } from 'react-router-dom'

class List extends PureComponent {
    render() {
        const { list, page, getMoreList } = this.props
        return (
            
{ list.map((item, index) => { return ( ... ) }) } ...
) } } ...

详情页面的跳转实现了。
2.我们来写一下Logo的跳主页。
(1)我们先改一下之前header组件的style
我们去掉了之前的attr属性href,把a标签换成了div。

//===>src/common/header/style.js
...
export const Logo = styled.div`
position:absolute;
top:0;
left:0;
display:block;
width:100px;
height:56px;
background:url(${logoPic});
background-size:contain;
`
...

(2)在Header组件添加Link

...
import { Link } from 'react-router-dom'

class Header extends Component {
...
    render() {
        const { focused, handleInputFocus, handleInputBlur, list } = this.props
        return (
            
                
                
                    
                        
                    
                   ...
                
            
        )
    }
}
...

还要改一个地方,之前Header组件和下面装Home组件和Detail组件的容器BrowserRouter是兄弟关系,所以不能用Link组件,我们要把他改成父子组件

//===>src/App.js
import React from 'react';
import Header from './common/header'
import store from './store'
import { Provider } from 'react-redux'
import { BrowserRouter, Route } from 'react-router-dom'
import Home from './pages/home';
import Detail from './pages/detail'
function App() {
  return (
    
      
        
); } export default App;

点击Logo,我们可以回到首页。
还有一个优化,如果数据发生一点改变,renter(){}就会渲染整个组件,这很费性能,是不合理的。我们希望只渲染数据有变化的组件。解决方案是,如果我们用了immutable数据类型,那么我们只需要把Component改成PureComponent就好了。
操作方法是:1.导入import React, { PureComponent } from 'react'
2.把Home、Topic、List、Recommend、Writer中的Component变成PureComponent

你可能感兴趣的:(19. 项目实战:首页开发(五))