使用React搭建個人部落格

ZALE發表於2018-03-07

專案地址: 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程式碼高亮
  • [ ] 美化頁面的樣式

部落格預覽

首頁

blog_home

部落格詳情頁

https://user-gold-cdn.xitu.io/2018/3/7/161fe5a89983b46e?w=1369&h=892&f=jpeg&s=219987

專案總結

接下來我大致介紹一下我在做部落格專案時的一些體會和感悟。

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 來改變 storestore 的改變會使得相應元件被更新,元件也會收到更新後的資料。其實 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)
複製程式碼

從程式碼可以看出,ProfileCardstore 獲取了 profile 物件的 blogCounttagCountcategoryCount 和一個 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'
複製程式碼

當載入頁面的時候,在外面樣式表中就能夠找到它。

react_import_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 似乎是一種全新的選擇,我個人非常喜歡這種寫法。

相關文章