前段時間接觸了下React,一直想要本身寫一個小Demo練手。在衆多應用中,考慮以後選擇了簡書來模仿,這段時間就利用了工做之餘的時間進行開發。主要用到了React+React-Router4+Redux+Redux-thunk+Immutable。然而寫文章也是能夠覆盤一下本身的開發過程,對本身仍是受益良多的。在這裏簡單敘述一下我仿簡書部分佈局以及功能實現的過程,僅作學習用途。html
技術棧以及組件庫
數據結構:ios
文件結構
┣━ build // 打包文件
┣━ public // 打包文件
┣━ api //假數據統一存儲
┣━ detail.json //文章頁數據
┣━ headerList.json //頭部熱門搜索數據
┣━ home.json //首頁統一數據
┣━ homeList.json //首頁加載更多文章數據
┣━ login.json //登陸數據
┣━ src //開發目錄
┣━ common //公用組件
┣━ header //頭部組件
┣━ store //Redux文件
┣━ actionCreators.js //action建立
┣━ constants.js //action.type常量文件
┣━ index.js //入口文件
┣━ reducer.js //reducer處理
┣━ store //UI組件
┣━ store //頭部樣式
┣━ pages //頁面
┣━ detail //文章頁
┣━ ...
┣━ detail //首頁
┣━ ...
┣━ detail //登陸頁
┣━ ...
┣━ detail //寫文章
┣━ ...
┣━ statics //靜態文件
┣━ ...
┣━ store //Redux數據
┣━ ...
┣━ App.js //入口及路由
┣━ index.js //js文件入口
┣━ style.js //全局樣式
┣━ .gitignore //git忽略上傳文件
┣━ package.json //模塊的描述文件
┣━ README.md //說明文件
┣━ yarn.lock //模塊的描述文件
複製代碼
效果預覽
實現主要幾個功能
用戶在已登陸狀態和未登陸狀態的界面是不一樣的,有些功能指定要在登陸狀態下才會有,所以會產生狀態的切換,在通常小項目中咱們可使用localStorage
來存儲狀態,也能夠用Redux,這裏我全部的數據都是使用Redux進行數據管理,在進入寫文章頁面調用了login組件下Redux-login狀態進行判斷,登陸攔截。git
class Write extends PureComponent {
render() {
const { loginStatus } = this.props;
console.log(loginStatus)
if(loginStatus) {
return (
<div>寫文章</div>
)
}else{
return <Redirect to="/login" />
}
}
componentDidMount() {
}
}
const mapState = (state) => ({
loginStatus: state.getIn(['login','login'])
});
複製代碼
這裏在Redux中儲存一個Page:1的數據,在每次點擊加載更多文章時page+1,而後對page進行改變。使得每次點擊page+1。github
在Home組件獲取到數據後儲存到Redux中,而後取出前十條數據,儲存到常量中。經過點擊事件對數據進行切換,同時出發動畫效果。(因爲使用了immutable
,因此要在循環的數據前將數據轉換爲不一樣JS數組)json
const { focused, list, page, mouseIn, totalPage, handleMouseEnter, handleMouseLeave, hanleChangePage } = this.props;
const newList = list.toJS(); //由於list目前是immutable數組,因此咱們要將他轉換爲普通JS數組,toJS是immutable內置方法
const pageList = [];
if(newList.length){
for(let i = (page -1) * 10; i < page * 10; i++){
pageList.push(
<SearchInfoItem key={newList[i]}>{newList[i]}</SearchInfoItem>
)
}
}
if(focused || mouseIn) {
return (
<SearchInfo
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
>
<SearchInfoTitle>
熱門搜索
<SearchInfoSwitch onClick={() => hanleChangePage(page,totalPage,this.spitIcon)}>
<i ref={(icon) => {this.spitIcon = icon}} className="iconfont spin"></i>
換一批
</SearchInfoSwitch>
</SearchInfoTitle>
<SearchInfoList>
{pageList}
</SearchInfoList>
</SearchInfo>
)
}else {
return null;
}
}
複製代碼
文章頁數據的獲取使用的動態路由
,經過路由傳參將當前所點擊文章的ID傳遞到文章頁。axios
import Detail from './pages/detail/loadable';
,否則獲取不到路由所傳遞的參數。class Detail extends PureComponent {
//dangerouslySetInnerHTML是當數據內容是HTML時使用,不會被轉義爲字符串
render() {
const { title, content } = this.props;
return (
<DetailWrapper>
<Header>{title}</Header>
<Content
dangerouslySetInnerHTML={{__html: content}}
/>
</DetailWrapper>
)
}
componentDidMount() {
let idPage = this.props.location.search;
const id = idPage.substring(4)
this.props.getDetail(id);
//使用動態路由獲取idthis.props.getDetail(this.props.match.params.id);
}
}
複製代碼
結語
因爲工做比較忙,因此只作了一些基礎的小功能。後面還有不少有待完善,等空餘時間多了出來回慢慢進行完善。因爲剛接觸React,因此作的不太好,不足之處還請指教。api
若是你初次接觸到React,或者對Demo感興趣的話能夠查看我GitHub源碼數組
若是對你有幫助,能夠star個人項目給我一點點的鼓勵,也但願有志同道和的能夠加入一塊兒討論,我也會第一時間幫你解答。bash