項目地址: github.com/zaleGZL/zal…css
若是你以爲項目不錯的話,歡迎點擊右上角 'star' 支持下,萬分感謝! ~(≧▽≦)/~前端
線上地址: guozeling.cn/blogsreact
之前我是用 hexo + next 來搭建本身的博客,但最近學習了 React 後,深深地被它的組件化開發思想所吸引,恰好寒假放假有時間,因此我就用 React 搭建了一個本身的博客。React 實際上只是對應 MVC 中的視圖層,要想搭建一個完整的應用,僅有 React 是不夠的,咱們還須要其它的庫或框架,例如用來管理數據的 redux,用於實現前端路由的 react-router 等等。ios
註明: 博客前端頁面沒有使用其它基於 React 的 CSS 框架,主要仍是想增強本身寫 CSS 能力。git
博客的後端是使用 Node.js 開發的,是基於 koa 並採用了 Restful API 架構實現的,完美實現先後端的分離,後端只須要負責提供數據,而路由的跳轉、數據渲染都是由前端實現。github
項目地址: github.com/zaleGZL/zal…web
接下來我大體介紹一下我在作博客項目時的一些體會和感悟。express
在使用 React 以後,我發現 React 它自己作的事情很是簡單,它僅僅只是一個視圖層的一個框架,它可以讓你使用 JSX 語法來寫HTML,並且它這種基於組件化的開發方式很是新穎,使得組件具有高可複用性。當在多人協做構建應用時,咱們每一個人只須要負責一個個小的組件,同時咱們也要儘可能下降組件與組件的耦合性,增大組件的內聚性,最終這一個個組件就可以構建出一個大型應用。redux
前端發展很是快速,老是會出現新的東西,之前在使用 express 搭建後端應用,那時候我知道有後端路由,就是請求的 URL 路徑來返回不一樣的內容,返回不一樣的頁面。而當我第一次據說前端路由時,我一開始覺得它是一個新的東西,其實否則,它僅僅是把後端的那一套搬過來了而已。在前端實現了路由,可使得當頁面的 URL 刷新時,不會發起該 URL 請求,而是根據不一樣的 URL 渲染不一樣的組件。axios
<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
函數裏)。
前端發展的初期,一開始你們都提倡內容與樣式分離,其實就是將 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'
複製代碼
當加載頁面的時候,在外面樣式表中就可以找到它。
但這樣寫會存在許多問題:
我我的比較喜歡 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 彷佛是一種全新的選擇,我我的很是喜歡這種寫法。