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

2020-07-22  本文已影响0人  小二的学习日记

返回顶部功能实现

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

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 (
            <HomeWrapper>
                <HomeLeft>
                    <img className="banner-img" src="https://upload.jianshu.io/admin_banners/web_images/4993/421ec96ccef8aea708c84ba2972b5be484695f25.png?imageMogr2/auto-orient/strip|imageView2/1/w/1250/h/540" alt='' />
                    <Topic />
                    <List />
                </HomeLeft>
                <HomeRight>
                    <Recommend />
                    <Writer />
                </HomeRight>
                {
                    this.props.showScroll ?
                        <BackTop onClick={this.handleScrollTop}>回到</BackTop>
                        : null
                }
            </HomeWrapper>
        )
    }

    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 (
            <div>
                {
                    list.map((item, index) => {
                        return (
                            <Link key={index} to='/detail'>
                                <ListItem key={index}>
                                  ...
                                </ListItem>
                            </Link>
                        )
                    })
                }
...
            </div>
        )
    }
}
...

详情页面的跳转实现了。
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 (
            <Fragment>
                <IconFontStyle />
                <HeaderWrapper>
                    <Link to='/'>
                        <Logo />
                    </Link>
                   ...
                </HeaderWrapper>
            </Fragment>
        )
    }
}
...

还要改一个地方,之前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 (
    <Provider store={store}>
      <BrowserRouter>
        <div>
          <Header />
          <Route path='/' exact component={Home}></Route>
          <Route path='/detail' exact component={Detail}></Route>
        </div>
      </BrowserRouter>
    </Provider >
  );
}

export default App;

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

上一篇下一篇

猜你喜欢

热点阅读