專案地址: github.com/zaleGZL/zal…
如果你覺得專案不錯的話,歡迎點選右上角 'star' 支援下,萬分感謝! ~(≧▽≦)/~
線上地址: guozeling.cn/blogs
前言
以前我是用 hexo + next 來搭建自己的部落格,但最近學習了 React 後,深深地被它的元件化開發思想所吸引,剛好寒假放假有時間,所以我就用 React 搭建了一個自己的部落格。React 實際上只是對應 MVC 中的檢視層,要想搭建一個完整的應用,僅有 React 是不夠的,我們還需要其它的庫或框架,例如用來管理資料的 redux,用於實現前端路由的 react-router 等等。
技術棧
前端
- react
- axios: 非同步請求
- react-router-dom: 前端路由
- redux: 管理整個應用資料
- redux-thunk: redux的中介軟體,多用於處理非同步action
- styled-components: CSS in JS 的一種,使得能夠在JS中寫原生的CSS
註明: 部落格前端頁面沒有使用其它基於 React 的 CSS 框架,主要還是想加強自己寫 CSS 能力。
後端
- koa
部落格的後端是使用 Node.js 開發的,是基於 koa 並採用了 Restful API 架構實現的,完美實現前後端的分離,後端只需要負責提供資料,而路由的跳轉、資料渲染都是由前端實現。
專案地址: github.com/zaleGZL/zal…
實現的功能
- [x] 部落格首頁列表展示
- [x] 部落格內容markdown
- [x] 部落格內容的目錄
- [x] 部落格的分類和標籤
- [x] 返回頂部
- [x] 響應式
- [x] 關於頁面(目前用於放簡歷,本人大三,求實習中...)
TODO
- [ ] 分類頁面
- [ ] 標籤頁面
- [ ] markdown程式碼高亮
- [ ] 美化頁面的樣式
部落格預覽
首頁
部落格詳情頁
專案總結
接下來我大致介紹一下我在做部落格專案時的一些體會和感悟。
React 僅僅是一個檢視層
在使用 React 之後,我發現 React 它本身做的事情非常簡單,它僅僅只是一個檢視層的一個框架,它能夠讓你使用 JSX 語法來寫HTML,而且它這種基於元件化的開發方式非常新穎,使得元件具備高可複用性。當在多人協作構建應用時,我們每個人只需要負責一個個小的元件,同時我們也要儘量降低元件與元件的耦合性,增大元件的內聚性,最終這一個個元件就能夠構建出一個大型應用。
前端路由
前端發展非常快速,總是會出現新的東西,以前在使用 express 搭建後端應用,那時候我知道有後端路由,就是請求的 URL 路徑來返回不同的內容,返回不同的頁面。而當我第一次聽說前端路由時,我一開始以為它是一個新的東西,其實不然,它僅僅是把後端的那一套搬過來了而已。在前端實現了路由,可以使得當頁面的 URL 重新整理時,不會發起該 URL 請求,而是根據不同的 URL 渲染不同的元件。
<Switch>
<Route exact path="/" component={BlogList} />
<Route exact path="/blogs" component={BlogList} />
<Route path="/blogs/:blogId" component={Blog} />
<Route path="/tags" component={OnDevelopingContent} />
<Route path="/categories" component={OnDevelopingContent} />
<Route path="/about" component={ResumeContent} />
<Route component={NotFoundContent} />
</Switch>
複製程式碼
上面的程式碼就是我的部落格應用最頂層的路由元件的部分程式碼,這裡是使用 react-router,並且根據不同的路由來渲染不同的元件。
如何管理應用資料
React 中的 state
其實就是來存放應用資料的,並且能夠傳遞給子元件,在構建一個小型應用時,state
的確夠用,但是在構建大型應用時就要好好考慮一下如何管理應用資料了。
state
其實存在以下幾個問題:
-
父元件若要將資料傳遞給孫元件或者更後代的元件,就需要所有中間元件的幫助幫忙傳遞,否則就需要用 React 中的
context API
來實現跨元件傳遞資料。 -
子元件的資料無法傳遞給父元件或者更頂層的元件。
-
應用的資料存放地過於分散。
而 Redux 的出現就解決了以上的問題,在 Redux 中只存在一個唯一的全域性 store
,整個應用的資料都存放在這裡,任何元件都可以能夠從 store
中獲得自己元件需要用到的資料,並且能夠通過派發 action
來改變 store
,store
的改變會使得相應元件被更新,元件也會收到更新後的資料。其實 Redux 就是使用 Context API
實現的,
const mapStateToProps = state => ({
blogCount: state.profile.blogCount,
tagCount: state.profile.tagCount,
categoryCount: state.profile.categoryCount
})
const mapDispatchToProps = dispatch =>
bindActionCreators(
{
requestGetProfileInfo
},
dispatch
)
export default connect(mapStateToProps, mapDispatchToProps)(ProfileCard)
複製程式碼
從程式碼可以看出,ProfileCard
從 store
獲取了 profile
物件的 blogCount
、tagCount
、categoryCount
和一個 requestGetProfileInfo
函式,requestGetProfileInfo
其實就是用來改變 store
的。connect
函式是 react-redux 的一個方法,用來連線 react 和 redux,呼叫該函式實際上返回一個高階元件,並且內部是做了很多的效能優化(主要在 shouldcomponentupdate
函式裡)。
CSS 應該怎麼寫
前端發展的初期,一開始大家都提倡內容與樣式分離,其實就是將 HTML 與 CSS 分開寫,在 HTML 中引用 CSS 資源。
但是隨著前端的發展,元件化開發越來被認可,似乎是一種趨勢。但是它卻與傳統的內容與樣式分離相違背。在元件化開發方式中,我們都提倡元件內聚性,將與該元件相關的 HTML、CSS、JavaScript 寫在一起,在我看來,這是元件化開發最適合的寫法。
在 React 寫 CSS 其實有很多種選擇,各有各的優點吧,蘿蔔青菜,各有所愛嘛,但讓我眼前一亮的卻是 styled-components 這個庫,它其實也是 CSS in JS 的一種。
元件中的內聯樣式
const divStyle = {
color: 'blue',
backgroundImage: 'url(' + imgUrl + ')',
};
function HelloWorldComponent() {
return <div style={divStyle}>Hello World!</div>;
}
複製程式碼
這其實跟在 HTML 中寫內聯樣式時一樣的,我覺得假如一個元件只需要修改某幾個樣式,是完全可以採用這個寫法,但是若要寫很多樣式,其實是不適合的。
外部樣式
reboot.css
*,
*::before,
*::after {
box-sizing: border-box;
}
body {
margin: 0 0 100px;
padding-top: 50px;
}
a {
text-decoration: none;
cursor: pointer;
}
複製程式碼
index.js
import './reboot.css'
複製程式碼
當載入頁面的時候,在外面樣式表中就能夠找到它。
但這樣寫會存在許多問題:
- 命名容易衝突
- 元件獨立性較差
- 無法按需載入
CSS in JS
我個人比較喜歡 styled-components,先來看看官方的例子。
// 建立一個Title元件並且它會渲染 h1 標籤,並且擁有以下的樣式
const Title = styled.h1`
font-size: 1.5em;
text-align: center;
color: palevioletred;
`;
// 建立一個Wrapper元件並且它會渲染 section 標籤,並且擁有以下樣式
const Wrapper = styled.section`
padding: 4em;
background: papayawhip;
`;
// 元件渲染
render(
<Wrapper>
<Title>
Hello World, this is my first styled component!
</Title>
</Wrapper>
);
複製程式碼
styled-components
的核心思想是將樣式與相應的元件繫結到一起,通過計算 CSS 樣式內容生成內容雜湊值,並且將該值作為該元件 className 的值,這完美地解決了命名衝突問題。
當然 styled-components
的強大之處不止於此,它還能夠實現 CSS 規則的繼承、擴充套件、根據父元件傳遞的 props 動態計算樣式等等。
CSS in JS 似乎是一種全新的選擇,我個人非常喜歡這種寫法。