到目前為止,首頁、文章詳情頁、動態頁、話題頁及小冊頁面內容完成了,看一下效果圖哈,資料不全,見諒哈!
實現過程
動態頁
該頁面從佈局來說分左右兩部分,左邊有分為輸入框和已發表內容部分。
- 輸入框部分
釋出按鈕的disabled狀態將根據輸入框是否有值來決定。功能類似todolist新增功能,可參考文章詳情頁面的釋出評論功能。
<div style={{background:'#fff',padding:'15px',position:'relative'}}>
<TextArea placeholder="告訴你個小祕密,發沸點時新增話題會被更多小夥伴看見呦~" style={{paddingBottom:'30px'}} autosize={{ minRows: 3}} onChange={this.handelInputChange.bind(this)}/>
{this.state.selectedTopic!==''?<span style={{position:'absolute',bottom:'60px',left:'28px',padding:'0 12px',border:'1px solid #007fff',userSelect:'none',height:'22px',borderRadius:'14px',color:'#007fff'}}>{this.state.selectedTopic}</span>:''}
<div style={{marginTop:'5px',display:'flex',justifyContent:'space-between'}}>
<ul style={sy1}>
<li style={sy2} onClick={this.handleBtn.bind(this,'exp')}>
<img alt='' src='//b-gold-cdn.xitu.io/v3/static/img/emoji.5594dbb.svg' />表情
</li>
<li style={sy2} onClick={this.handleBtn.bind(this,'pic')}>
<img alt='' src='//b-gold-cdn.xitu.io/v3/static/img/active_file.d265f4e.svg' />圖片
</li>
<li style={sy2} onClick={this.handleBtn.bind(this,'link')}>
<img alt='' src='//b-gold-cdn.xitu.io/v3/static/img/active_link.b1a6832.svg' />連結
</li>
<Popover placement="bottom" content={<TopicList handleTopic={this.handleTopic.bind(this)} />} trigger="click">
<li style={sy2} onClick={this.handleBtn.bind(this,'topic')}>
<img alt='' src='//b-gold-cdn.xitu.io/v3/static/img/topic.6a87bb7.svg' />話題
</li>
</Popover>
</ul>
<Button type="primary" disabled={this.state.disabledBtn} onClick={this.handlePressEnter.bind(this)}>釋出</Button>
</div>
</div>
複製程式碼
輸入框內容發生變化事件
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('請輸入沸點內容');
}
}
複製程式碼
- 新增話題
<div style={{background:'#fff'}}>
<Search
placeholder="搜尋話題"
onSearch={value => this.handleSearch(value)}
style={{ width: '100%' }}
/>
<List
itemLayout="horizontal"
dataSource={this.state.topicListData}
style={{height:'300px',overflow:'auto'}}
renderItem={item => (
<List.Item style={{cursor:'pointer'}} onClick={this.handleClick.bind(this,item.title)}>
<List.Item.Meta
avatar={<Avatar size={42} shape="square" src={item.img} />}
title={item.title}
description={<div>{item.followers}關注 {item.num}沸點</div>}
/>
</List.Item>
)}
/>
</div>
複製程式碼
搜尋框回車搜尋事件:
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 }) => (
<span onClick={this.handleClick.bind(this,tag)}>
<Icon type={type} style={{ marginRight: 8 }} />
{text}
</span>
);
const PopoverContent=(id)=>{
return <p style={{cursor:'pointer'}} onClick={this.handleReport.bind(this,id)}>舉報</p>
}
return (
<div>
<List
itemLayout="vertical"
size="large"
dataSource={this.state.listData}
renderItem={item => (
<List.Item
key={item.author}
actions={
[
<IconText type="like" text={item.likeNum===0?'贊':item.likeNum} tag='like' />,
<IconText type="message" text={item.commentNum===0?'評論':item.commentNum} tag='comment' />,
<IconText type="share-alt" text="分享" tag='share' />
]
}
extra={
<div>
{!item.isFollowed && <Button style={{borderColor:'#6cbd45',color:'#6cbd45'}} onClick={()=>this.handleFollow(item.id)}>{item.isFollowed?'已關注':'關注'}</Button>}
<Popover placement="bottom" content={<PopoverContent author={item.author} />} trigger="click">
<span style={{cursor:'pointer',margin:'10px'}}>...</span>
</Popover>
</div>
}
>
<List.Item.Meta
// avatar={<Avatar size={45} src={item.avatar} />}
avatar={<Popover placement="top" content={<PersonalPop info={item} handleFollow={(id)=>this.handleFollow(id)} />}>
<Avatar size={45} src={item.avatar} />
</Popover>}
title={<Popover placement="top" content={<PersonalPop info={item} handleFollow={(id)=>this.handleFollow(id)} />}>
<span style={{cursor:'pointer'}}>{item.author}</span>
</Popover>}
description={<div><span>{item.description}</span><span style={{margin:'0 5px'}}>·</span><span>{timeUtil.getTimeAgo(item.editTime)}</span></div>}
/>
{item.content}
</List.Item>
)}
/>
</div>
);
}
複製程式碼
使用者頭像滑鼠滑過會出現詳情,使用了popover元件,具體內容是單獨抽離的一個PersonalPop元件。每一項根據isFollowed值判斷是否顯示關注按鈕,如果沒有關注,點選可關注。
- 右側內容
右側內容統一使用card元件實現,利用Redux獲取登入使用者資訊。
render() {
const { Meta } = Card;
return (
<div className='dynamicSide'>
<Card style={{ width: '100%' }} className='card1'>
<Meta
avatar={<Avatar size={62} src={this.props.userImage} />}
title={this.props.userId}
description={this.props.userDesc}
/>
<div>
<ul>
<li>
<p className='liTitle'>沸點</p>
<p className='liNum'>{this.state.userInfo.topNum}</p>
</li>
<li>
<p className='liTitle'>關注</p>
<p className='liNum'>{this.state.userInfo.following}</p>
</li>
<li>
<p className='liTitle'>關注者</p>
<p className='liNum'>{this.state.userInfo.follower}</p>
</li>
</ul>
</div>
</Card>
<Card
title="你可能感興趣的人"
style={{ width: '100%' ,marginTop:'10px'}}
className='card2'
>
<List
itemLayout="horizontal"
dataSource={this.state.interestList}
renderItem={item => (
<List.Item actions={[<Button>關注</Button>]}>
<List.Item.Meta
avatar={<Avatar size={40} src={item.userImage} />}
title={item.user}
description={item.desc}
/>
</List.Item>
)}
/>
<div className='user-recommend-footer' onClick={this.changeInterestList.bind(this)}>
<Icon type="sync" />換一批
</div>
</Card>
<div style={{marginTop:'10px'}}>
<TopicCard title='關注的話題' link='/topics' list={this.state.attentionTopic} />
</div>
<div style={{marginTop:'10px'}}>
<TopicCard title='更多話題' link='/topics' list={this.state.allTopic} />
</div>
</div>
);
}
複製程式碼
鑑於關注的話題和更多話題內容結構類似,故抽離為一個公用元件,且為函式式元件。
function TopicCard({ title,list,link }){
return (
<Card
title={title}
extra={<a href={link} style={{color:'#007fff'}}>全部></a>}
style={{ width: '100%' }}
className='topicCard'
>
<List
itemLayout="horizontal"
dataSource={list}
renderItem={item => (
<List.Item>
<List.Item.Meta
avatar={<Avatar shape="square" size={40} src={item.userImage} />}
title={item.title}
description={<div style={{color:'#8a9aa9'}}><span>{item.followNum}關注</span>·<span>{item.hotNews}沸點</span></div>}
/>
</List.Item>
)}
/>
</Card>
);
}
複製程式碼
React元件可分為函式元件(Functional Component )和類元件(Class Component),劃分依據是根據元件的定義方式。函式元件使用函式定義元件,類元件使用ES6 class定義元件。
函式元件的寫法要比類元件簡潔,不過類元件比函式元件功能更強大。類元件可以維護自身的狀態變數,即元件的state,類元件還有不同的生命週期方法,可以讓我們能夠在元件的不同階段(掛載、更新、解除安裝)對元件做更多的控制,進行不同的操作。但函式元件的使用可以從思想上讓你在設計元件時進行更多思考,更加關注邏輯控制和顯示的分離,設計出更加合理的元件結構。實際操作中,當一個元件不需要管理自身狀態時,可以把它設計成函式元件,當你有足夠的理由發現它需要“升級”為類元件時,再把它改造為類元件。因為函式元件“升級”為類元件是有一定成本的,這樣就會要求你做這個改造前更認真地思考其合理性,而不是僅僅為了一時的方便就使用類元件。
話題頁
同樣適用函式式元件function TopicItem({item,showCount}){
const {id,topicName,topicImage,topicCount,followedNum,topicNum,isFollowed}=item;
return (
<div className='topicItem'>
<Badge count={showCount?topicCount:0} overflowCount={999}>
<Avatar shape="square" size={72} src={topicImage} />
</Badge>
<div style={{marginLeft:'15px'}}>
<div>
<NavLink to={`/topic/${id}`}>{topicName}</NavLink>
</div>
<div style={{color:'#8a9aa9',marginTop:'5px'}}>
<span>{followedNum}關注</span>·
<span>{topicNum}沸點</span>
</div>
<div className={isFollowed?'hasFollowed':'noFollow'}>
{isFollowed?'已關注':'+關注'}
</div>
</div>
</div>
);
}
複製程式碼
關注的話題資料其實是全部話題的子集,在父頁面呼叫的時候根據資料中的isFollowed屬性進行一次篩選。
componentDidMount(){
const list=[...this.state.allTopicList];
const followedTopicList=list.filter(item=>item.isFollowed);
this.setState({
followedTopic:[...followedTopicList]
})
}
複製程式碼
小冊頁
- 頭部的導航
function TopNav({tags,changeLink}){
return (
<ul>
{tags.map((item,index)=>{
return <li key={item.path} onClick={()=>changeLink(item.path)}>
<NavLink to={`/books${item.path}`}>{item.text}</NavLink>
</li>
})}
</ul>
)
}
複製程式碼
- 小冊列表
使用ant-design中的list元件進行基本佈局
render() {
return (
<div>
<List
size="large"
bordered
dataSource={this.state.bookList}
renderItem={item => (
<List.Item className='bookList' onClick={()=>this.showInfo(item.bookId)}>
<img alt='books' src={item.img} />
<div>
<div style={{color:'#000',fontSize:'20px',fontWeight:400}}>
{item.isPresell && <span className="presale">預售</span> }
<span className='bookName'>{item.name}</span>
</div>
<div className='bookDesc'>{item.desc}</div>
<div className='bookAuthor'>
<NavLink to={`/user/:${item.userId}`}>
<Avatar size={26} src={item.userImage} />
<span style={{color:'#000',marginLeft:'5px'}}>{item.author}</span>
</NavLink>
<span style={{color:'#71777c',margin:'0 10px',whiteSpace:'nowrap',overflow:'hidden'}}>{item.selfDesc}</span>
</div>
<div className='other'>
{item.isBuy?<span className='bought'>已購買</span>:<span className='price'>¥{item.price}</span>}
<span className='message'>{item.chapterNum}小節</span>
{item.isBuy && <span className='message'>閱讀時長{item.readTime}分</span>}
<span className='message'>{item.purchaseNum}購買</span>
</div>
</div>
</List.Item>
)}
/>
</div>
);
}
複製程式碼
會根據屬性是否預售isPresell和是否已經購買isBuy來判斷顯示不同內容。
相關文章
相關詳細程式碼可檢視github,不要忘了star哦!工作中主要是以vue作為主要技術棧,這是第一次使用React+React-router+Redux來構建專案,不足之處還請大家多多包涵。
金三已過,銀四會是什麼樣子呢?