返回顶部功能实现
今天我们要做的是,回到顶部的功能。
我们通过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
网友评论