1. 实现“简书”首页
我们首先分析“简书”首页的布局,可以发现整体分为左右两个部分。
左边是一个带有轮播图的专题推荐栏目,右边是一个推荐作者列表。因此,我们可以搭建一个基本的框架:
class Home extends Component{
render(){
return (
<HomeWrapper>
<HomeLeft>
<img className='banner-img' src='https://upload-images.jianshu.io/upload_images/13448242-20871e9f865fb242.jpg?imageMogr2/auto-orient/strip|imageView2/2/w/594/format/webp'/>
</HomeLeft>
<HomeRight>Right</HomeRight>
</HomeWrapper>
);
}
}
export default Home;
为了更好地组织代码,我们可以使用styled-components来渲染组件:
import styled from 'styled-components';
export const HomeWrapper = styled.div`
overflow:hidden;
width: 960px;
margin: 0 auto;
`;
export const HomeLeft = styled.div`
float:left;
margin-left:15px;
padding-top:30px;
width: 625px;
.banner-img{
width:625px;
height:270px;
}
`;
export const HomeRight = styled.div`
width: 240px;
float:right;
`;
2. 实现专题区域界面
首先我们希望实现类似简书首页的专题区域:
主要是实现其中 Item 的设计。我们目前的代码如下:
javascriptCopy code
import React, { Component } from 'react';
import { TopicItem, TopicWrapper } from "../style";
import { connect } from 'react-redux';
class Topic extends Component {
render() {
return (
<TopicWrapper>
<TopicItem>
<img className='topic-pic'
src='https://upload-images.jianshu.io/upload_images/1741702-7d340c9913d5ada8.jpg?imageMogr2/auto-orient/strip|imageView2/2/w/424/format/webp'/>
社会热点
</TopicItem>
// ...
</TopicWrapper>
);
}
}
export default connect()(Topic);
以下是关于样式的说明:
TopicWrapper的overflow属性是为了适配Item的float样式,保证可以自己测量得到所需的高度。- 具体的颜色样式直接参考简书调试获取。
- 下面的是图片的 class,
display设置为block是为了不影响文字的效果。 - 其他的 margin 可能最后还需要进行微调。
3. Home 界面的数据设计
之前的 header 界面已经搭建好了基于 Redux 的数据管理框架,Home 界面也需要。这里主要是专题区域的 list 需要这个数据。
3.1 Home 的 store 目录
import { fromJS } from 'immutable';
const defaultState = fromJS({
topicList: [{
id:1,
title:'社会热点',
imgUrl:'https://upload-images.jianshu.io/upload_images/1741702-7d340c9913d5ada8.jpg?imageMogr2/auto-orient/strip|imageView2/2/w/424/format/webp'
},{
id:2,
title:'手绘',
imgUrl:'https://upload-images.jianshu.io/upload_images/1741702-7d340c9913d5ada8.jpg?imageMogr2/auto-orient/strip|imageView2/2/w/424/format/webp'
}]
});
export default (state = defaultState, action) => {
return state;
}
接下来,我们需要将其分配到根目录下的 reducer 中:
import { combineReducers } from 'redux-immutable';
import { reducer as headReducer } from '../common/header/store';
import { reducer as homeReducer } from '../pages/home/store';
export default combineReducers({
header: headReducer,
home: homeReducer
});
最后,我们需要在 Topic 组件中获取这个 list,然后循环渲染出 Item。注意,这个数据是 immutable,所以需要使用 get 方法获取数据:
import React, {Component} from 'react';
import {TopicItem, TopicWrapper} from "../style";
import {connect} from 'react-redux';
class Topic extends Component {
render() {
return (
<TopicWrapper>
{
this.props.list.map((item) => {
return (
<TopicItem key={item.get('id')}>
<img className='topic-pic'
src={item.get('imgUrl')}/>
{item.get('title')}
</TopicItem>
)
})
}
</TopicWrapper>
);
}
}
const mapStateToProps = (state) => ({
list: state.get('home').get('topicList')
});
export default connect(mapStateToProps, null)(Topic);