如何使用react和 graphql 开发一个blog


logo_og-1024x538.png

本文由cosmic.js 友情提供,谢谢支持的伙伴以及sitepoint 网站提供。
 
本文主要描述使用react 以及 graphql . cosmic.js 来创建一个基础的博客文章系统。这是一个使用流行技术栈快捷,轻量级的好产品。下面我们开始。
 
开始
 
请确认在你的机器上安装了node .js 和Npm 。如果没有请到node 官网下载安装安装,然后我们继续。
 
首先创建app的文件夹。如果你也喜欢使用终端命令行,可以使用如下的命令:
 
Mkdir simple-react-blog 
Cd simple-react-blog 
 
接下来,我们添加一个叫 package.json 的文件到当前文件夹,用来引用当前app需要的文件依赖:
 
Vim package.json 
 
请添加如下内容,
 
[code]{{
 "scripts": {
   "dev": "node server.js",
   "build": "next build",
   "start": "next build; NODE_ENV=production node server.js"
 },
 "dependencies": {
   "axios": "^0.16.2",
   "express": "^4.16.2",
   "lodash": "^4.17.4",
   "next": "^4.0.3",
   "next-routes": "^1.1.0",
   "react": "^16.0.0",
   "react-dom": "^16.0.0"
 }}
[/code]
多么完美的依赖。来看看,我们都用了那些插件:
 
Axios是一个promised式的HTTP客户端,用来和graphql以及cosmic.js通信。
 
Next.js是一个我们通用 react 框架。
 
Next routes是一个动态路由。
 
Express是一个服务端的框架。
 
React用来处理用户界面。
 
我们的脚本需要以上依赖运行和部署。运行以下命令安装上述的依赖:
 
Npm i
 
他等价于NPM INSTALL
 
构建我们的博客
 
下一步,我们来构建博客的页面,创建一个页面文件夹以及index.js文件。
 
Vim index.js
 
添加如下代码到其中:
 
[code]import axios from 'axios'import _ from 'lodash'import Footer from './partials/footer'import Header from './partials/header'import helpers from '../helpers'import config from '../config'export default class extends React.Component {
 static async getInitialProps({ req }) {
   const query = `{
     objects(bucket_slug: "${config.bucket.slug}") {
       _id
       type_slug
       slug
       title
       metadata
       created_at
     }
   }`
   return await axios.post(`https://graphql.cosmicjs.com/v1`, { query })
   .then(function (response) {
     return {
       cosmic: {
         posts: _.filter(response.data.data.objects, { type_slug: 'posts' }),
         global: _.keyBy(_.filter(response.data.data.objects, { type_slug: 'globals' }), 'slug')
       }
     }
   })
   .catch(function (error) {
     console.log(error)
   })
 }
 render() {
   if (!this.props.cosmic)
     return <div>Loading...</div>
   return (
     <div>
       <Header cosmic={ this.props.cosmic }/>
       <main className="container">
         {
           this.props.cosmic.posts &&
           this.props.cosmic.posts.map(post => {
             const friendly_date = helpers.friendlyDate(new Date(post.created_at))
             post.friendly_date = friendly_date.month + ' ' + friendly_date.date              return (
                <div className="card" data-href={`/${post.slug}`} key={post._id}>
                 {
                   post.metadata.hero.imgix_url &&
                   <a href={`/${post.slug}`} className="blog-post-hero blog-post-hero--short" style={{ backgroundImage: `url(${post.metadata.hero.imgix_url})`}}></a>
                 }
                 <div className="card-padding">
                   <h2 className="blog__title blog__title--small">
                     <a href={`/${post.slug}`}>{post.title}</a>
                   </h2>
                   <div className="blog__author">
                     <a href={`/author/${post.metadata.author.slug}`}>
                       <div className="blog__author-image" style={{ backgroundImage: `url(${post.metadata.author.metafields[0].imgix_url}?w=100)`}}></div>
                     </a>
                     <div className="blog__author-title">by <a href={`/author/${post.metadata.author.slug}`}>{post.metadata.author.title}</a> on {post.friendly_date}</div>
                     <div className="clearfix"></div>
                   </div>
                   <div className="blog__teaser droid" dangerouslySetInnerHTML={{__html: post.metadata.teaser}}></div>
                   <div className="blog__read-more">
                     <a href={`/${post.slug}`}>Read more...</a>
                   </div>
                 </div>
               </div>  
             )
           })
         }
       </main>
       <Footer />
     </div>
   )
 }}
[/code]
 
以下兴奋的事情发生了。
 
1. 我们导入了需要的模块:Axios,Lodash以及其他helpers和组件。
2. 我们使用了partials推入,并如header头部和footer尾部版权部分。
关于partials可以参考GitHub。
3. 我们请求Comic.js以及grapthql,需要返回如下内容:
ID,typeslug,slug,title,metadata以及create at
4. 我们设置主进程在我们的组件渲染到comic对象。我们使用lodash去解析posts和全局对象类型。
5. 我们返回表单数组数据和图片URL到主博客feed流。
 
简单的表单查询
 
针对简单的查询,我们添加POST属性到props。Post是用来从博客文章的slug中查询匹配的内容。代码如下:
 
[code]const gql_query = `{
 objects(bucket_slug: "${config.bucket.slug}") {
   type_slug
   slug
   title
   content
   metadata
   created_at
 }
}`return await axios.post(`https://graphql.cosmicjs.com/v1`, { query: gql_query }).then(function (response) {
 return {
   cosmic: {
     posts: _.filter(response.data.data.objects, { type_slug: 'posts' }),
     global: _.keyBy(_.filter(response.data.data.objects, { type_slug: 'globals' }), 'slug'),
     post: _.find(response.data.data.objects, { slug: query.slug }),
   }
 }}).catch(function (error) {
 console.log(error)})}
[/code]
 
完整的代码请你到github上查询下载。
 
小结
 
本文的完整代码均在cosmicjs博客上提供下载。托管的不同版本也在github上。你可以轻松get到,源代码包括dashboard等相关组件。
 
如果你有相关问题,欢迎留言给我。
 
 
 
作者:tony spiro
编译:前端老白
来源:sitepoint.com

0 个评论

要回复文章请先登录注册