在本教程系列的前一部分中,您了解了如何实现注册和登录功能。在本教程的这一部分中,您将实现用户主页以及添加和显示博客文章的功能。
入门
让我们首先从教程的第一部分克隆源代码。
https://github.com/royagasthyan/reactBlogApp-SignUp
克隆目录后,导航到项目目录并安装require d 依赖项。
cd ReactBlogApp-SignUp npm install
启动节点.js 服务器,您将在 http://localhost:7777/index.html#/运行应用程序。
创建用户主页
用户尝试登录应用程序后,您需要验证用户凭据,如果有效,则创建会话。要在 node.js 应用程序中使用会话,您需要express-session使用 Node Package Manager (npm) 进行安装。
npm install express-session --save
需要express-session在app.js文件中。
var session = require('express-session');
要使用会话,您需要设置会话密码。
app.use(session({secret: 'my-secret'}));
sessions现在定义一个在全局范围内调用的变量。
var sessions
使用请求参数在方法中sessions分配变量。/signin
sessions=req.session;
使用该sessions变量,您可以将登录的用户名保留在会话中。
sessions.username = user_name;
home.html在应用程序的文件夹内创建一个名为的html文件。这是它的外观:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="description" content=""> <meta name="author" content=""> <title>React Blog App</title> <link href="bootstrap.min.css" rel="stylesheet"> <link href="jumbotron-narrow.css" rel="stylesheet"> </head> <body> <div> <div class="header clearfix"> <nav> <ul class="nav nav-pills pull-right"> <li role="presentation"><a href="#">Home</a></li> <li role="presentation"><a href="#">Add</a></li> <li role="presentation"><a href="#">Logout</a></li> </ul> </nav> <h3>React Blog App</h3> </div> <div> <div> <a href="#" class="list-group-item active"> <h4>List group item heading</h4> <p>Donec id elit non mi porta gravida at eget metus. Maecenas sed diam eget risus varius blandit.</p> </a> <a href="#"> <h4>List group item heading</h4> <p>Donec id elit non mi porta gravida at eget metus. Maecenas sed diam eget risus varius blandit.</p> </a> <a href="#"> <h4>List group item heading</h4> <p>Donec id elit non mi porta gravida at eget metus. Maecenas sed diam eget risus varius blandit.</p> </a> </div> </div> <footer> <p>© 2016 Company, Inc.</p> </footer> </div> </body> </html>
创建一个名为的快速路由/home,它将为有效用户呈现主页。
app.get('/home', function (req, res) { if(sessions && sessions.username){ res.sendFile(__dirname + '/html/home.html'); } else{ res.send('unauthorized'); } })
从上面的代码中可以看出,当用户被重定向到/home路由时,如果sessions并且sessions.username存在,就会渲染主页。
修改signin方法以在用户验证成功时发送成功响应。
app.post('/signin', function (req, res) { sessions=req.session; var user_name=req.body.email; var password=req.body.password; user.validateSignIn(user_name,password,function(result){ if(result){ sessions.username = user_name; res.send('success'); } }); })
上面的成功响应在 React 端解析,如果成功,用户被重定向到/homeexpress 路由。在文件中,在方法内部的组件内部,修改代码以重定向到主页。main.jsxSigninsignIn
signIn(){ axios.post('/signin', { email: this.state.email, password: this.state.password }) .then(function (response) { if(response.data == 'success'){ window.location.assign('http://localhost:7777/home') } }) .catch(function (error) { console.log(error); }); }
保存上述更改并让Node 服务器恢复正常。使用有效的用户名和密码登录,您将被重定向到主页。
将上述博文显示修改为 React 组件。创建一个名为home.jsx. 在该 home.jsx文件中,创建一个名为 React 的组件, ShowPost该组件将呈现博客文章列表。在 React 组件渲染方法中移动静态 HTML。这是ShowPostReact 组件的外观:
class ShowPost extends React.Component { constructor(props) { super(props); } render() { return ( <div className="list-group"> <a href="#" className="list-group-item active"> <h4 className="list-group-item-heading">List group item heading</h4> <p className="list-group-item-text">Donec id elit non mi porta gravida at eget metus. Maecenas sed diam eget risus varius blandit.</p> </a> <a href="#" className="list-group-item"> <h4 className="list-group-item-heading">List group item heading</h4> <p className="list-group-item-text">Donec id elit non mi porta gravida at eget metus. Maecenas sed diam eget risus varius blandit.</p> </a> <a href="#" className="list-group-item"> <h4 className="list-group-item-heading">List group item heading</h4> <p className="list-group-item-text">Donec id elit non mi porta gravida at eget metus. Maecenas sed diam eget risus varius blandit.</p> </a> </div> ) } }
修改home.html页面以包含所需的 React 库。这是修改后的home.html页面:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="description" content=""> <meta name="author" content=""> <title>React Blog App</title> <link href="bootstrap.min.css" rel="stylesheet"> <link href="jumbotron-narrow.css" rel="stylesheet"> <script src="https://fb.me/react-15.1.0.js"></script> <script src="https://fb.me/react-dom-15.1.0.js"></script> <script src="https://npmcdn.com/react-router@3.0.2/umd/ReactRouter.min.js"></script> <script src="https://unpkg.com/axios/dist/axios.min.js"></script> <script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script> </head> <body> <div> <div class="header clearfix"> <nav> <ul class="nav nav-pills pull-right"> <li role="presentation"><a href="#">Home</a></li> <li role="presentation"><a href="#">Add</a></li> <li role="presentation"><a href="#">Logout</a></li> </ul> </nav> <h3>React Blog App</h3> </div> <div id="app"> </div> <footer> <p>© 2016 Company, Inc.</p> </footer> </div> <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script> <script type="text/babel" src="home.jsx"> </script> </body> </html>
从上面的 HTML 代码中可以看出,容器 div 已命名为app,其中将显示 React 组件。
保存上述更改并重新启动节点服务器。登录到博客应用程序,然后在主页上,您将ShowPost呈现 React 组件。
现在您需要动态填充帖子列表中的值。在此之前,让我们创建一个页面来添加帖子。单击上面的Add 超链接后,您需要显示添加博客文章的页面。
添加 Post React 组件
让我们创建一个添加文章 React 组件来添加博客文章。它将由一个标题输入框和一个主题文本区域组成。在 中home.jsx,创建一个 AddPost React 组件来添加博客文章。这是AddPostReact 组件的外观:
class AddPost extends React.Component { render() { return ( <div className="col-md-5"> <div className="form-area"> <form role="form"> <br styles="clear:both" /> <div className="form-group"> <input type="text" className="form-control" id="title" name="title" placeholder="Title" required /> </div> <div className="form-group"> <textarea className="form-control" type="textarea" id="subject" placeholder="Subject" maxlength="140" rows="7"></textarea> </div> <button type="button" id="submit" name="submit" className="btn btn-primary pull-right">Add Post</button> </form> </div> </div> ) } }
当用户输入标题和帖子主题时,需要在 React 组件中处理文本更改事件。将以下更改事件处理程序添加到AddPostReact 组件。
handleTitleChange(e){ this.setState({title:e.target.value}) } handleSubjectChange(e){ this.setState({body:e.target.value}) }
将 on change 事件添加到AddPost呈现 HTML。
<div className="form-group"> <input type="text" onChange={this.handleTitleChange} className="form-control" id="title" name="title" placeholder="Title" required /> </div> <div className="form-group"> <textarea className="form-control" onChange={this.handleSubjectChange} type="textarea" id="subject" placeholder="Subject" maxlength="140" rows="7"></textarea> </div>
在 React 构造方法中绑定状态变量和事件。
constructor(props) { super(props); this.handleTitleChange = this.handleTitleChange.bind(this); this.handleSubjecChange = this.handleSubjectChange.bind(this); this.state = { title:'', subject:'' }; }
当用户点击Add Post按钮时,您需要将标题和主题从 React 用户界面发布到 Node.js 后端,以将其保存在mongodb数据库中。addPost创建一个在React 组件中调用的方法AddPost来发布标题并服从 Node.js 请求处理程序。以下是 React 组件中的addPost方法的AddPost外观:
addPost(){ axios.post('/addPost', { title: this.state.title, subject: this.state.subject }) .then(function (response) { console.log('response from add post is ',response); hashHistory.push('/') }) .catch(function (error) { console.log(error); }); }
如上面的代码所示,您曾经axios将博客文章详细信息发布到 Node.js 服务器。
现在您需要创建一个帖子模块,该模块将处理添加和获取帖子详细信息。post.js在项目目录中创建一个名为的文件。在post.js文件中,导出一个 addPost将帖子详细信息插入 MongoDB 数据库的方法。需要MongoClientand createaddPost方法在 MongoDB 数据库中插入帖子详细信息。这是post.js文件的外观:
var MongoClient = require('mongodb').MongoClient; var assert = require('assert'); var url = 'mongodb://localhost:27017/Blog'; module.exports = { addPost: function(title, subject, callback){ MongoClient.connect(url, function(err, db) { db.collection('post').insertOne( { "title": title, "subject": subject },function(err, result){ assert.equal(err, null); console.log("Saved the blog post details."); if(err == null){ callback(true) } else{ callback(false) } }); }); } }
如上面的代码所示,您使用连接器连接到 MongoDB 数据库并插入了一条记录。执行操作后,您检查错误(如果有)并将状态返回给回调函数。
在app.js文件中,创建一个名为的请求处理程序,addPost该处理程序addPost将从post.js. 这是它的外观:
app.post('/addpost', function (req, res) { var title = req.body.title; var subject = req.body.subject; post.addPost(title, subject ,function(result){ res.send(result); }); })
保存上述更改并重新启动 Node.js 服务器。登录到应用程序,单击添加链接,然后输入详细信息以添加帖子。完成后,单击Add Post按钮,详细信息应保存在 MongoDB 数据库中。
显示 Post React 组件
首先,您需要从 MongoDB中获取保存的帖子详细信息。在post.js文件中,创建一个名为的方法,该方法GetPost将获取帖子详细信息。这是它的外观:
getPost: function(callback){ MongoClient.connect(url, function(err, db){ db.collection('post', function (err, collection) { collection.find().toArray(function (err, list) { callback(list); }); }); }) }
上面的代码从 MongoDB 集合中获取详细信息,将其转换为列表,然后将其发送回回调函数。在home.jsx文件中,在ShowPost组件内部,获取 componentDidMount 方法中的帖子详细信息。这是它的外观:
componentDidMount(){ var self = this; axios.post('/getPost', { }) .then(function (response) { }) .catch(function (error) { console.log('error is ',error); }); }
上面的代码向 Node.js 服务器方法发出一个 post 请求,该方法/getPost将调用文件getPost中的方法post.js。这是文件中的/getPost方法app.js。
app.post('/getpost', function (req, res) { post.getPost(function(result){ res.send(result); }); })
在axios成功回调中获取帖子详细信息后,将详细信息保存在状态数组变量中。声明一个posts在构造函数内部调用的变量ShowPost。
constructor(props) { super(props); this.state = { posts:[] }; }
在axios ajax调用的成功回调中,设置状态变量如图:
self.setState ({posts: response.data})
获得帖子详细信息后,您需要在 React 组件的 render 方法中动态创建所需的 HTML。这是它的外观:
render() { return ( <div className="list-group"> { this.state.posts.map(function(post,index) { return <a href="#" key={index} className="list-group-item active"> <h4 className="list-group-item-heading">{post.title}</h4> <p className="list-group-item-text">{post.subject}</p> </a> }) } </div> ) }
上面的代码迭代posts状态变量并动态创建 HTML。保存上述更改并重新启动 Node.js 服务器。登录博客应用程序并使用主页上的添加按钮创建一些博客文章。添加帖子后,它们将显示在主页上。
最后
在本教程中,您了解了如何创建 React 组件以添加和显示博客文章。在本教程系列的下一部分中,您将学习如何添加删除和更新博客文章的功能。