项目地址: 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 彷佛是一种全新的选择,我我的很是喜欢这种写法。