2-10 首页性能优化 PureComponent 以及路由跳转

前面我们把首页的功能完成了,现在我们做一下性能调优,与跳转到详情页面。

首先,我们看到 src/pages/home 下面几乎所有组件,都调用了react-redux 的 connect 方法 与 store 做了连接。

这就会有一个问题,只要store 发生了改变,这些组件就都会被重新渲染。

那我们可以使用一个生命周期函数 shouldComponentUpdate 中判断,只有在与本组件相关数据变化时,才会更新。

当然,React 中提供了新的组件类型,使得我们可以省略在每个组件中使用 shouldComponentUpdate 的繁琐步骤。这种组件类型是PureComponent .

我们把 src/pages/home 下面的组件 extands 都改为 PureComponent 。如下

import React, {PureComponent} from 'react';
import { connect } from 'react-redux';
import {HomeWrapper, HomeLeft, HomeRight, BackTop } from './style';
import List from './components/List';
import Recommend from './components/Recommend';
import Topic from './components/Topic';
import Writer from './components/Writer';
import bannerImage from '../../statics/ooo.jpg';
import { actionCreators } from './store';

class Home extends PureComponent {
    handleScrollTop () {
        window.scrollTo(0,0);
    }
    render () {
        return (
            <HomeWrapper>
                <HomeLeft>
                    <img
                        className="banner-img"
                        src={bannerImage}
                        alt=''
                    />
                    <Topic></Topic>
                    <List></List>
                </HomeLeft>
                <HomeRight>
                    <Recommend></Recommend>
                    <Writer></Writer>
                </HomeRight>
                {this.props.showScroll ? <BackTop onClick={this.handleScrollTop}>顶部</BackTop> : null }
            </HomeWrapper>
        )
    }
    componentDidMount () {
        this.props.changeHomeData();
        this.bindEvents();
    }
    bindEvents() {
        window.addEventListener("scroll", this.props.changeScrollTopShow);
    }
    componentWillUnmount () {
        window.removeEventListener("scroll", this.props.changeScrollTopShow);
    }
}

const mapState = (state) => {
    return {
        showScroll: state.get("home").get("showScroll")
    }
}
const mapDispatch = (dispatch) => {
    return {
        changeHomeData () {
            const action = actionCreators.getHomeInfo();
            dispatch(action);
        },
        changeScrollTopShow () {
            console.log();
            if ( document.documentElement.scrollTop > 100) {
                dispatch(actionCreators.toggleShowScroll(true));
            } else {
                dispatch(actionCreators.toggleShowScroll(false));
            }
        }
    }
}
export default connect(mapState, mapDispatch)(Home);

其它组件同理。

注意,这里之所以可以正确使用 PureComponent 是因为我们的数据,使用了一个数据框架 immutable.js 。它保证了我们的数据是 immutable 的。PureComponent 与 immutable.js 数据管理相结合,PureComponent 使用起来就没有问题。如果在项目里,没有使用 immutable.js 管理数据,PureComponent 使用的时候就可能会遇到坑。

下面我们来实现,点击 List 中的 项目 跳转到详情页面。

打开 src/pages/home/components 下的 List.js

可以像下面这样,使用<a>标签

import React, {PureComponent} from 'react';
import { connect } from 'react-redux';
import { ListItem, ListInfo, LoadMore } from '../style';
import { actionCreators } from '../store';

class List extends PureComponent {
    render () {
        const { articleList, getMoreList, articlePage } = this.props;
        return (
            <div>
                { 
                    articleList.map( (item) => {
                        return (
                            <a key={item.get("id")} href="/detail">
                                <ListItem key={item.get('id')}>
                                    <img
                                        className='pic'
                                        src={item.get('imgURL')}
                                        alt=''
                                    />
                                    <ListInfo>
                                        <h3 className='title'>{item.get('title')}</h3>
                                        <p className='desc'>{item.get('desc')}</p>
                                    </ListInfo>
                                </ListItem>
                            </a>
                            
                        )
                    } )
                }
                <LoadMore onClick={ () => getMoreList(articlePage)}>更多文字</LoadMore>
            </div>
        )
    }
}

const mapStateToProps = (state) => {
    return {
        articleList: state.get("home").get("articleList"),
        articlePage: state.get("home").get("articlePage")
    }
};

const mapDispatchToProps = (dispatch) => {
    return {
        getMoreList (page) {
            dispatch(actionCreators.getMoreList(page));
        }
    }
};

export default connect(mapStateToProps, mapDispatchToProps)(List);

但是这样,点击链接的时候,就会重新发送获取页面的请求,这样就不是单页面程序。再发送请求会耗掉一部分性能。我们使用react-router-dom,如下。

import React, {PureComponent} from 'react';
import { connect } from 'react-redux';
import { ListItem, ListInfo, LoadMore } from '../style';
import { actionCreators } from '../store';
import { Link } from "react-router-dom";

class List extends PureComponent {
    render () {
        const { articleList, getMoreList, articlePage } = this.props;
        return (
            <div>
                { 
                    articleList.map( (item) => {
                        return (
                            <Link key={item.get("id")} to="/detail">
                                <ListItem key={item.get('id')}>
                                    <img
                                        className='pic'
                                        src={item.get('imgURL')}
                                        alt=''
                                    />
                                    <ListInfo>
                                        <h3 className='title'>{item.get('title')}</h3>
                                        <p className='desc'>{item.get('desc')}</p>
                                    </ListInfo>
                                </ListItem>
                            </Link>
                            
                        )
                    } )
                }
                <LoadMore onClick={ () => getMoreList(articlePage)}>更多文字</LoadMore>
            </div>
        )
    }
}

const mapStateToProps = (state) => {
    return {
        articleList: state.get("home").get("articleList"),
        articlePage: state.get("home").get("articlePage")
    }
};

const mapDispatchToProps = (dispatch) => {
    return {
        getMoreList (page) {
            dispatch(actionCreators.getMoreList(page));
        }
    }
};

export default connect(mapStateToProps, mapDispatchToProps)(List);

猜你喜欢

转载自blog.csdn.net/purple_lumpy/article/details/89359990