到目前为止,首页、文章详情页、动态页、话题页及小册页面内容完成了,看一下效果图哈,数据不全,见谅哈!
实现过程
动态页
该页面从布局来说分左右两部分,左边有分为输入框和已发表内容部分。
- 输入框部分
我这里采用了ant-design中的input作为输入框,而掘金是采用了可编辑的div来实现输入内容,通过设置contenteditable="true"实现,感兴趣的小伙伴可查阅相关资料。
发布按钮的disabled状态将根据输入框是否有值来决定。功能类似todolist添加功能,可参考文章详情页面的发布评论功能。
输入框内容发生变化事件
handelInputChange=(e)=>{
if(e.target.value.trim()!==''){
this.setState({
disabledBtn:false,
inputValue:e.target.value
})
}else{
this.setState({
disabledBtn:true
})
}
}
发布按钮事件
handlePressEnter=()=>{
if(this.state.inputValue!==''){
console.log('发布沸点')
}else{
message.error('请输入沸点内容');
}
}
- 添加话题
this.handleSearch(value)}
style={{ width: '100%' }}
/>
(
}
title={item.title}
description={{item.followers}关注 {item.num}沸点}
/>
)}
/>
搜索框回车搜索事件:
handleSearch=(value)=>{
const list=[...this.state.storeListData];
if(value!==''){
const searchList=list.filter(item=>item.title.indexOf(value)>-1);
this.setState({
topicListData:searchList
})
}else{
this.setState({
topicListData:list
})
}
}
话题列表点击事件:
handleClick=(val)=>{
this.props.handleTopic(val);
}
这里向父组件传递了一个val代表当前点击话题,关于父子组件传值的相关说明前面文章做了介绍,这里不再赘述。
- 已发表的话题列表
使用ant-design的list组件实现
render() {
const IconText = ({ type, text,tag }) => (
{text}
);
const PopoverContent=(id)=>{
return 举报
}
return (
(
,
,
]
}
extra={
{!item.isFollowed && }
} trigger="click">
...
}
>
}
avatar={this.handleFollow(id)} />}>
}
title={this.handleFollow(id)} />}>
{item.author}
}
description={{item.description}·{timeUtil.getTimeAgo(item.editTime)}}
/>
{item.content}
)}
/>
);
}
用户头像鼠标滑过会出现详情,使用了popover组件,具体内容是单独抽离的一个PersonalPop组件。每一项根据isFollowed值判断是否显示关注按钮,如果没有关注,点击可关注。
- 右侧内容
右侧内容统一使用card组件实现,利用Redux获取登录用户信息。
render() {
const { Meta } = Card;
return (
}
title={this.props.userId}
description={this.props.userDesc}
/>
-
沸点
{this.state.userInfo.topNum}
-
关注
{this.state.userInfo.following}
-
关注者
{this.state.userInfo.follower}
(
关注]}>
}
title={item.user}
description={item.desc}
/>
)}
/>
换一批
);
}
鉴于关注的话题和更多话题内容结构类似,故抽离为一个公用组件,且为函数式组件。
function TopicCard({ title,list,link }){
return (
全部>}
style={{ width: '100%' }}
className='topicCard'
>
(
}
title={item.title}
description={{item.followNum}关注·{item.hotNews}沸点}
/>
)}
/>
);
}
React组件可分为函数组件(Functional Component )和类组件(Class Component),划分依据是根据组件的定义方式。函数组件使用函数定义组件,类组件使用ES6 class定义组件。
函数组件的写法要比类组件简洁,不过类组件比函数组件功能更强大。类组件可以维护自身的状态变量,即组件的state,类组件还有不同的生命周期方法,可以让我们能够在组件的不同阶段(挂载、更新、卸载)对组件做更多的控制,进行不同的操作。但函数组件的使用可以从思想上让你在设计组件时进行更多思考,更加关注逻辑控制和显示的分离,设计出更加合理的组件结构。实际操作中,当一个组件不需要管理自身状态时,可以把它设计成函数组件,当你有足够的理由发现它需要“升级”为类组件时,再把它改造为类组件。因为函数组件“升级”为类组件是有一定成本的,这样就会要求你做这个改造前更认真地思考其合理性,而不是仅仅为了一时的方便就使用类组件。
话题页
function TopicItem({item,showCount}){
const {id,topicName,topicImage,topicCount,followedNum,topicNum,isFollowed}=item;
return (
{topicName}
{followedNum}关注·
{topicNum}沸点
{isFollowed?'已关注':'+关注'}
);
}
关注的话题数据其实是全部话题的子集,在父页面调用的时候根据数据中的isFollowed属性进行一次筛选。
componentDidMount(){
const list=[...this.state.allTopicList];
const followedTopicList=list.filter(item=>item.isFollowed);
this.setState({
followedTopic:[...followedTopicList]
})
}
小册页
- 头部的导航
function TopNav({tags,changeLink}){
return (
{tags.map((item,index)=>{
return - changeLink(item.path)}>
{item.text}
})}
)
}
- 小册列表
使用ant-design中的list组件进行基本布局
render() {
return (
(
this.showInfo(item.bookId)}>
{item.isPresell && 预售 }
{item.name}
{item.desc}
{item.author}
{item.selfDesc}
{item.isBuy?已购买:¥{item.price}}
{item.chapterNum}小节
{item.isBuy && 阅读时长{item.readTime}分}
{item.purchaseNum}购买
)}
/>
);
}
会根据属性是否预售isPresell和是否已经购买isBuy来判断显示不同内容。
相关文章
- 使用React构建精简版本掘金(一)
- 使用React构建精简版本掘金(二)
- 使用React构建精简版本掘金(三)
相关详细代码可查看github,不要忘了star哦!工作中主要是以vue作为主要技术栈,这是第一次使用React+React-router+Redux来构建项目,不足之处还请大家多多包涵。
金三已过,银四会是什么样子呢?