Null's Blog

React版博客系列4--Article组件与ArticleList组件

系列链接:

1.React版博客系列1–基础说明与标签组件
2.React版博客系列2–分页组件设计
3.React版博客系列3–路由系统
4.React版博客系列4–Article组件与ArticleList组件

先上demo

本系列源码: blog_react
数据服务: blog_api
线上预览: http://react.nullcn.com

接上篇

react-router骨架已经搭好,博客的主体部分为显示博文已经相关的操作。查看归档、分页、显示单篇文章等。
个人自定义一页显示三篇博文,所以,ArticleList组件内包含三个Article组件,当然,这个不会写死。
先看Article 的render方法,这里使用了html5的新标签article,this.props.route这个判断的作用是让Article组件知道,目前所处的状态是查看单篇文章(Article自己根据文章名称读取接口)还是多篇文章组合(ArticleList读取相应的接口,把每篇文章的内容通过props传递进来):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
render(){
if(this.props.route){
return (
<article>
<header>
<h2>
<a href="#">{this.state.title}</a>
</h2>
</header>
<div className="article-meta clearfix">
<time className="left">{this.state.timeStr}</time>
<ul className="tags left"></ul>
<ul className="tags right">
{
this.state.tags.map(function(item,index){
return (<li><Link to={"/tag"+"/"+item.tag+"/"}>{item.tagName}</Link></li>)
})
}
</ul>
</div>
<div className="markdown-body" dangerouslySetInnerHTML={{__html: this.state.post}}>
</div>
</article>
)
}else{
return(
<article>
<header>
<h2>
<Link to={"/"+this.props.articleModel.time.year+"/"+this.props.articleModel.time.month+"/"+this.props.articleModel.name}>{this.props.articleModel.title}</Link>
</h2>
</header>
<div className="article-meta clearfix">
<time className="left" >{this.props.articleModel.timeStr}</time>
<ul className="tags right">
{
this.props.articleModel.tags.map(function(item,index){
return (<li key={index}><Link to={"/tag"+"/"+item.tag+"/"}>{item.tagName}</Link></li>)
})
}
</ul>
</div>
<div className="markdown-body" dangerouslySetInnerHTML={{__html: this.props.articleModel.post}}>
</div>
</article>
)
}
}

那相应的,Article获取文章内容的方法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
componentDidMount(){
this.getArticle();
}
getArticle(){
let self = this;
let url = Settings.getServiceUrl();
//判断是否是从router进入 从router进入这是是undefined
if(this.props.params){
url = url + '/' + this.props.params.year + '/' + this.props.params.month + '/' + this.props.params.name;
$.ajax({
url:url,
type:'GET',
}).done(function(result){
self.setState({
title:result.article.title,
timeStr:result.article.timeStr,
tags:result.article.tags,
post:result.article.post
});
}.bind(self));
}
}

ArticleList组件

ArticleList组件除了管理Article之外,还需管理分页组件,关于分页组件,请查看本系列第二篇React版博客系列2–分页组件设计
核心方法getArticleList:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
componentDidMount(){
this.getArticleList(this.props);
}
componentWillReceiveProps(nextProps){
this.getArticleList(nextProps);
}
getArticleList(props){
let self = this;
let url = Settings.getServiceUrl();
let queryType = props.route.to.queryType;
switch(queryType){
case '/':
if(props.params.pageIndex){
url = url + '/page/' + props.params.pageIndex + '/';
}
break;
case 'tag':
let keyword = props.params.tag;
url = url + '/tag/' + keyword + '/';
if(props.params.pageIndex){
url = url + 'page/' + props.params.pageIndex + '/';
}
break;
case 'archive':
url = url + '/' + props.params.year + '/' + props.params.month + '/';
if(props.params.pageIndex){
url = url + 'page/' + props.params.pageIndex + '/';
}
break;
}
$.ajax({
url:url,
type:'GET',
cache:false
}).done(function(result){
self.setState({
queryType:queryType,
list:result.list,
pageIndex: result.pagination.pageIndex,
pageCount: result.pagination.pageCount,
prefix: result.pagination.prefix||''
});
}.bind(self));
}

getArticleList需要根据不同的参数查询不同的文章列表,比如普通分页、标签分页、归档分页等,而这些都是由上层的骨架router传递进来的,所以有了queryType变量,并提取出查询的具体参数。同样的,分页组件亦需要依赖于这些参数构建分页的前缀等:

1
2
3
4
5
6
7
8
9
10
11
12
render(){
return(
<div>
{
this.state.list.map(function(item,index){
return <Article articleModel={item} key={index} />
})
}
<Pagination onChange={this.onChange} pageIndex={this.state.pageIndex} pageCount={this.state.pageCount} prefix={this.state.prefix} />
</div>
);
}

ArticleList组件的完成意味着打通了从router到Article的全部展示流程,其中实现了自己的分页、标签、归档功能,当然,还包括了几个没那么核心的header、copyright、information组件等,一个说简单也不简单的博客系统已经初步完成,react为前端同学提供了一整套组件化思路,各位可以按照自己的想法实现自己的网站。

#后记
至此,React版博客系列系列已经完结,github上也早已开源了全部源码blog_react,要查看某些具体的细节,欢迎clone下来交流。
围绕React,亦产生了一整套单向数据流(flux、reflux、redux)。本系列并不打算讲任何一种单向数据流方案,因为在理解了react思路之后,flux、reflux、redux其实十分简单,根据口味自行选用即可。