├── .gitignore ├── README.md ├── app.js ├── bin └── www ├── package.json ├── public ├── bundle.js ├── javascripts │ ├── commentBox.js │ └── index.js └── stylesheets │ └── style.css ├── routes ├── comment.js ├── index.js ├── schema.js └── users.js ├── views └── index.html └── webpack.config.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | public/data/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React官网发表评论实例重写 加入后台及绑定数据库 2 | 3 | 后台使用express,并把数据存入mongodb数据库,前端加入webpack编译,react语法完全用ES6重写,并利用setState更新状态来取消官网极其影响性能的轮询。 4 | 5 | ##使用方式 6 | 7 | clone后运行npm install(推荐使用淘宝镜像cnpm,会快很多),再开启mongodb,然后npm start 8 | 然后访问[http://localhost:8888]我们就可以看到项目跑起来了。 9 | 10 | ##功能 11 | 12 | 一个简单的发表评论的功能,可以删除评论。发表和删除都做到实时刷新。 13 | 14 | 15 | ##一点感想 16 | 17 | React的这个实例看似简单,但是我在重写的时候确是踩了不少的坑。因为一开始对于React部分的代码理解不够深入,我在用express搭建后台和试图用状态更新替代原本的每两秒轮询一次的时候,都遇到了不少问题。随着我在论坛(如stackoverflow)查询相关的问题和文档,问题逐渐解决。当查到论坛上和我相同的问题被解答并解决时,竟然有一种幸福感╮(╯▽╰)╭ 。嗯,问题总是能解决的。 -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var path = require('path'); 3 | var favicon = require('serve-favicon'); 4 | var logger = require('morgan'); 5 | var cookieParser = require('cookie-parser'); 6 | var bodyParser = require('body-parser'); 7 | var comment = require('./routes/comment'); 8 | 9 | var app = express(); 10 | 11 | // view engine setup 12 | var engine = require('consolidate'); 13 | app.set('views', path.join(__dirname, 'views')); 14 | app.engine('html', engine.mustache); 15 | app.set('view engine', 'html'); 16 | 17 | // uncomment after placing your favicon in /public 18 | //app.use(favicon(path.join(__dirname, 'public', 'favicon.ico'))); 19 | app.use(logger('dev')); 20 | app.use(bodyParser.json()); 21 | app.use(bodyParser.urlencoded({ extended: false })); 22 | app.use(cookieParser()); 23 | app.use(express.static(path.join(__dirname, 'public'))); 24 | 25 | 26 | // 对所有(/)URL或路由返回index.html 27 | app.get('/', function (req, res) { 28 | res.render('index'); 29 | }); 30 | app.get('/comments', comment.list); 31 | app.get('/comments/:id', comment.get); 32 | app.delete('/comments/:id', comment.delete,comment.list); 33 | app.post('/comments', comment.add,comment.list); 34 | app.put('/comments/:id', comment.update); 35 | 36 | // 启动一个服务,监听从8888端口进入的所有连接请求 37 | var server = app.listen(8888, function(){ 38 | var host = server.address().address; 39 | var port = server.address().port; 40 | console.log('mongod --dbpath C:\Users\12510\Desktop\case\express+webpack\commentbox\public\data Listening at http://%s:%s', host, port); 41 | }); 42 | 43 | module.exports = app; 44 | -------------------------------------------------------------------------------- /bin/www: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /** 4 | * Module dependencies. 5 | */ 6 | 7 | var app = require('../app'); 8 | var debug = require('debug')('commentbox:server'); 9 | var http = require('http'); 10 | 11 | /** 12 | * Get port from environment and store in Express. 13 | */ 14 | 15 | var port = normalizePort(process.env.PORT || '3000'); 16 | app.set('port', port); 17 | 18 | /** 19 | * Create HTTP server. 20 | */ 21 | 22 | var server = http.createServer(app); 23 | 24 | /** 25 | * Listen on provided port, on all network interfaces. 26 | */ 27 | 28 | server.listen(port); 29 | server.on('error', onError); 30 | server.on('listening', onListening); 31 | 32 | /** 33 | * Normalize a port into a number, string, or false. 34 | */ 35 | 36 | function normalizePort(val) { 37 | var port = parseInt(val, 10); 38 | 39 | if (isNaN(port)) { 40 | // named pipe 41 | return val; 42 | } 43 | 44 | if (port >= 0) { 45 | // port number 46 | return port; 47 | } 48 | 49 | return false; 50 | } 51 | 52 | /** 53 | * Event listener for HTTP server "error" event. 54 | */ 55 | 56 | function onError(error) { 57 | if (error.syscall !== 'listen') { 58 | throw error; 59 | } 60 | 61 | var bind = typeof port === 'string' 62 | ? 'Pipe ' + port 63 | : 'Port ' + port; 64 | 65 | // handle specific listen errors with friendly messages 66 | switch (error.code) { 67 | case 'EACCES': 68 | console.error(bind + ' requires elevated privileges'); 69 | process.exit(1); 70 | break; 71 | case 'EADDRINUSE': 72 | console.error(bind + ' is already in use'); 73 | process.exit(1); 74 | break; 75 | default: 76 | throw error; 77 | } 78 | } 79 | 80 | /** 81 | * Event listener for HTTP server "listening" event. 82 | */ 83 | 84 | function onListening() { 85 | var addr = server.address(); 86 | var bind = typeof addr === 'string' 87 | ? 'pipe ' + addr 88 | : 'port ' + addr.port; 89 | debug('Listening on ' + bind); 90 | } 91 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "commentbox", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "node ./bin/www" 7 | }, 8 | "dependencies": { 9 | "body-parser": "~1.15.1", 10 | "consolidate": "^0.14.5", 11 | "cookie-parser": "~1.4.3", 12 | "debug": "~2.2.0", 13 | "express": "~4.13.4", 14 | "jade": "~1.11.0", 15 | "morgan": "~1.7.0", 16 | "mustache": "^2.3.0", 17 | "serve-favicon": "~2.3.0" 18 | }, 19 | "devDependencies": { 20 | "babel-core": "^6.18.2", 21 | "babel-loader": "^6.2.8", 22 | "babel-preset-es2015": "^6.18.0", 23 | "babel-preset-react": "^6.16.0", 24 | "consolidate": "^0.14.5", 25 | "jquery": "^3.1.1", 26 | "jsx-loader": "^0.13.2", 27 | "marked": "^0.3.6", 28 | "mongoose": "^4.7.1", 29 | "mustache": "^2.3.0", 30 | "react": "^15.4.1", 31 | "react-dom": "^15.4.1", 32 | "webpack": "^1.13.3", 33 | "webpack-dev-middleware": "^1.8.4" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /public/javascripts/commentBox.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import marked from 'marked'; 4 | import $ from 'jquery'; 5 | 6 | class Comment extends React.Component { 7 | onclick (index){this.props.click(this.props.index)} 8 | rawMarkup () { 9 | let rawMarkup = marked(this.props.children.toString(), {sanitize: true}); 10 | return { __html: rawMarkup }; 11 | } 12 | render () { 13 | return ( 14 |