运行效果

实战Node:Node实现留言板_html
实战Node:Node实现留言板_bootstrap_02
实战Node:Node实现留言板_表单_03
实战Node:Node实现留言板_表单_04

运行步骤
  1. 安装所需依赖npm install
    实战Node:Node实现留言板_bootstrap_05
  2. 运行app.js后即可访问http://localhost:3000/
知识点
  1. 执行npm init 初始化包

  2. 安装所需依赖>npm i body-parser ejs express moment morgan --save

  3. 格式化时间moment(new Date()).format('YYYY-MM-DD HH:mm:ss')

  4. ejs 模板引擎的运用

    // 注册模板引擎
    app.set('views', path.join(__dirname, 'views'));
    app.set('view engine', 'ejs');
    
  5. 设置用户表单提交数据的接收中间件

    // 设置用户表单提交数据的接收中间件,所有提交的信息都会保存在req.body
    app.use(bodyParser.urlencoded({extended:false}));
    
  6. 界面重定向

    // 回到主界面 重定向
    res.redirect('/');
    
  7. 设置全局变量,运用于服务器整个生命周期。

    let entries = [];
    app.locals.entries = entries;
    
代码

app.js

const express = require('express');
const bodyParser = require('body-parser');
const morgan = require('morgan');
const moment = require('moment');
const path = require('path');

let app = express();

// 注册模板引擎
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

// 设置全局变量,运用于服务器整个生命周期
let entries = [];
app.locals.entries = entries;

// 设置用户表单提交数据的接收中间件,所有提交的信息都会保存在req.body
app.use(bodyParser.urlencoded({extended:false}));

app.get('/', (req, res) => {
   res.render('index');
});

app.get('/new',(req,res)=>{
   res.render('new');
});
// 处理数据提交
app.post('/new',(req,res,next)=>{
   // 判断
   if(!req.body.title || !req.body.content){
      res.status(400).send('留言内容必须要有内容和标题!');
      return;
   }
   // 保留用户留言
   entries.push({
      title:req.body.title,
      content:req.body.content,
      published:moment(new Date()).format('YYYY-MM-DD HH:mm:ss'),
   });
   // 回到主界面 重定向
   res.redirect('/');
});
// 渲染404界面
app.use((req,res)=>{
   res.status(404).render('404');
});
app.listen(3000,()=>{
   console.log('服务器已经启动');
});

header.ejs

<!doctype html>
<html lang="zh-cn">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
    <title>留言板</title>
</head>
<body>

footer.ejs

<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
</body>
</html>

index.ejs

<%- include('header'); -%>

<h2 class="text-center mt-5 mb-2">留言板</h2>
<div class="text-center">
    <a href="/new" class="btn btn-sm btn-danger">留言</a>
</div>
<div class="container mt-2 mb-2">
    <div class="row">

            <% if(entries.length){%>
            <%entries.forEach(function (entry) {%>
            <div class="card mb-2" style="width: 100%;">
                <div class="card-body">
                    <h5 class="card-title"><%=entry.title%></h5>
                    <h6 class="card-subtitle mb-2 text-muted"><%=entry.published%></h6>
                    <p class="card-text"><%=entry.content%></p>
                </div>
            </div>
            <%})%>
            <%} else{%>
                <span class="p-2">暂无留言!</span><a class="p-2"href="/new">去添加一条留言</a>
            <%}%>

    </div>
</div>
<%- include('footer'); -%>


404.ejs

<%- include('header'); -%>
<div class="container text-center mt-5 mp-5 text-danger">
    <h2>提示:404!您访问的页面不存在</h2>
</div>
<%- include('footer'); -%>

new.ejs

<%- include('header'); -%>

<div class="container">
    <h3 class="text-center mt-4 mb-3">请写下留言:</h3>
    <form method="post" role="form">
        <div class="form-group">
            <label for="title">留言的标题:</label>
            <input type="text" class="form-control" id="title" name="title" placeholder="请输入标题" required>
        </div>
        <div class="form-group">
            <label for="title">留言的内容:</label>
            <textarea rows="5" style="resize: none" class="form-control" id="content" name="content" placeholder="请输入内容" required></textarea>
        </div>
        <div class="form-group">
            <input type="submit" value="提交留言" class="btn btn-danger float-right">
        </div>
    </form>
</div>

<%- include('footer'); -%>