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

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

作者: 小二的学习日记 | 来源:发表于2020-07-22 23:41 被阅读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

    相关文章

      网友评论

          本文标题:19. 项目实战:首页开发(五)

          本文链接:https://www.haomeiwen.com/subject/zolxlktx.html