目录结构

styles.css
body {
background: #0d1521;
font-family: tahoma;
color: #989898;
}
#todo-table {
position: relative;
width: 95%;
background: #090d13;
margin: 0 auto;
padding: 20px;
box-sizing: border-box;
}
#todo-table form:after {
margin: 0;
content: '';
display: block;
clear: both;
}
input[type="text"] {
width: 30%;
padding: 20px;
background: #181c22;
border: 0;
float: left;
font-size: 20px;
color: #989898;
}
button {
padding: 20px;
width: 30%;
float: left;
background: #23282e;
border: 0;
box-sizing: border-box;
color: #fff;
cursor: pointer;
font-size: 20px;
}
ul {
list-style-type: none;
padding: 0;
margin: 0;
}
li {
width: 100%;
padding: 20px;
box-sizing: border-box;
font-family: arial;
font-size: 20px;
cursor: pointer;
letter-spacing: 1px;
}
li:hover {
text-decoration: line-through;
background: rgba(0, 0, 0, 0.2);
}
todo-list.js
$(document).ready(function() {
$('form').on('submit', function(event) {
event.preventDefault();
var item = $('form input');
var todo = { item: item.val().trim() };
$.ajax({
type: 'POST',
url: '/todo',
data: todo,
success: function(data) {
//do something with the data via front-end framework
location.reload();
}
});
return false;
});
$('li').on('click', function() {
var item = $(this).text().trim().replace(/ /g, "-");
$.ajax({
type: 'DELETE',
url: '/todo/' + item,
success: function(data) {
//do something with the data via front-end framework
location.reload();
}
});
});
});
todo.ejs
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>To Do List</title>
<link rel="stylesheet" href="../assets/styles.css" type="text/css">
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<script src="../assets/todo-list.js"></script>
</head>
<body>
<div id="todo-table">
<form>
<input type="text" name="item" placeholder="Add New Item..." required/>
<button type="submit">Add Item</button>
</form>
<ul>
<% todos.forEach(function(todo){ %>
<li><%= todo.item %></li>
<%}) %>
</ul>
</div>
</body>
</html>
todoController.js
var bodyParser = require('body-parser');
var urlencodedParser = bodyParser.urlencoded({extended:false});
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/test', {useNewUrlParser: true, useUnifiedTopology: true});
var todoScheme = mongoose.Schema({
item:String
});
var todo = mongoose.model('Todo',todoScheme);
// var item = todo({item:'buy flowers'}).save(function(err) {
// if(err) throw err;
// console.log('save success');
// });
// var data = [{item:'milk'},{item:'orange'},{item:'banana '}];
module.exports = function(app) {
app.get('/todo',function(req,res) {
todo.find({},function(err,data) {
if(err) throw err;
res.render('todo',{todos:data});
});
});
app.post('/todo', urlencodedParser,function(req,res) {
todo(req.body).save(function(err,data) {
if(err) throw err
res.json(data);
});
// data.push(req.body);
});
app.delete('/todo/:item',function(req,res) {
console.log(req.params.item);
// 需要把横线替换成空格
todo.find({item:req.params.item.replace(/-/g, " ")}).remove(function(err,data) {
if(err) throw err;
res.json(data);
});
// data = data.filter(function(todo) {
// // 空格变成横线 因为路由不支持空格
// return todo.item.replace(/ /g, "-") !== req.params.item;
// });
// res.json(data);
});
}
app.js
var express = require('express');
var path = require('path');
var todoController = require('./controllers/todoController');
var app = express();
// 设置ejs模板引擎
app.set('view engine','ejs');
// 设置静态文件存放位置
app.use(express.static('public'));
todoController(app);
app.listen(3000);
console.log('listen 300 start');
package.json
{
"name": "file-explorer",
"version": "0.0.1",
"description": "A command-file file explorer",
"dependencies": {
"body-parser": "^1.19.0",
"ejs": "^3.0.1",
"express": "^4.17.1",
"mongoose": "^5.9.6",
"multer": "^1.4.2"
},
"scripts": {
"start": "node app.js"
},
"main": "app.js",
"devDependencies": {},
"author": "",
"license": "ISC"
}