常用鏈接
1.介紹
-
express
- 基于 Node.js 的 web 框架
- 用于快速搭建網站和應用,如博客、商場、聊天室、為前端提供 API
- 熱門、健全、簡單、少走彎路
- 簡單路由系統
- 集成模版引擎
- 中間件系統
-
快速開始
-
npm init -y
默認模式生成package.json
-
npm install --save express
安裝框架 -
npm install -g nodemon
方便調試,nodemon xxx
啟動應用
-
var express = require('express')
var app = express()
app.get('/', function (req, res) {
res.send('this is homepage')
})
app.listen(3000)
2.請求與響應
- 學會查看 官網 API 文檔,最快最全,這個文檔太清晰易懂了
- res.send([body])
- req.ip
res.send(new Buffer('whoop'));
res.send({ some: 'json' });
res.send('<p>some html</p>');
res.status(404).send('Sorry, we cannot find that!');
res.status(500).send({ error: 'something blew up' });
res.json({ user: 'tobi' });
res.status(500).json({ error: 'message' });
req.ip
// => "127.0.0.1"
// GET /search?q=tobi+ferret
req.query.q
// => "tobi ferret"
// example.com/users?sort=desc
req.path
// => "/users"
3.路由參數
- 路由參數是動態的
// http://127.0.0.1:3000/profile/1/user/able
app.get('/profile/:id/user/:name', function (req, res) {
console.dir(req.params) // 顯示屬性 { id: '1', name: 'able' }
res.send("You requested " + req.params.id + req.params.name)
})
- 路由參數支持正則表達式
app.get('/ab?cd', function (req, res) {
res.send('ab?cd')
})
4.查詢字符串
- 文檔 req.query
// GET /shoes?order=desc&shoe[color]=blue&shoe[type]=converse
req.query.order
// => "desc"
req.query.shoe.color
// => "blue"
req.query.shoe.type
// => "converse"
// http://127.0.0.1:3000/?find=hot
app.get('/', function (req, res) {
console.dir(req.query) // => { find: 'hot' }
res.send('home page: ' + req.query.find)
})
5.POST請求和postman工具
-
使用 body-parser 包,處理 post 請求
- body-parser 文檔
-
npm install body-parser --save
安裝 - 查看文檔,使用例子
postman 工具,用來圖形化模擬瀏覽器發送各種請求
-
- HTTP/1.1 協議規定的 HTTP 請求方法有 OPTIONS、GET、HEAD、POST、PUT、DELETE、TRACE、CONNECT 這幾種
- POST 一般用來向服務端提交數據
- application/x-www-form-urlencoded 普通表單提交
- multipart/form-data 可以上傳文件的表單
var bodyParser = require('body-parser')
// create application/json parser
var jsonParser = bodyParser.json()
// 使用中間件,在請求和響應中間處理 create application/x-www-form-urlencoded parser
var urlencodedParser = bodyParser.urlencoded({ extended: false })
app.post('/', urlencodedParser, function (req, res) {
console.dir(req.body)
res.send('ok')
})
app.post('/upload', jsonParser, function (req, res) {
console.dir(req.body)
res.send('ok')
})
6.上傳文件
- Multer 包 處理上傳文件
Multer is a node.js middleware for handling multipart/form-data, which is primarily used for uploading files.
安裝
npm install --save multer
上傳文件的表單需要指定
enctype="multipart/form-data"
postman 上傳文件,post body form-data
// form.html
<form action="/upload" method="post" enctype="multipart/form-data">
<h2>上傳logo圖片</h2>
<input type="file" name="logo">
<input type="submit" value="提交">
</form>
// 創建目錄,上傳文件
var createFolder = function (folder) {
try {
fs.accessSync(folder);
} catch (e) {
fs.mkdirSync(folder);
}
};
var uploadFolder = './upload/';
createFolder(uploadFolder);
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, uploadFolder);
},
filename: function (req, file, cb) {
cb(null, file.originalname);
}
});
var upload = multer({ storage: storage });
app.get('/form', function (req, res) {
var form = fs.readFileSync('./form.html', { encoding: "utf8" })
res.send(form)
})
app.post('/upload', upload.single('logo'), function (req, res) {
console.dir(req.file); // 列出文件的所有屬性
res.send({ 'ret_code': 0 })
})
7.模版引擎介紹
- 直接使用
res.sendFile(__dirname + '/form.html')
響應網頁
app.get('/form', function (req, res) {
// var form = fs.readFileSync('./form.html', { encoding: "utf8" })
// res.send(form)
res.sendFile(__dirname + '/form.html')
})
-
模版引擎 EJS
npm install ejs --save
- 模版文件擴展名
.ejs
- ejs 模版的Tags 特殊,非對稱的,有前面和后面的,如
%> Plain ending tag
app.get('/form/:name', function (req, res) {
var person = req.params.name
res.render('form', { person: person })
})
// views/form.ejs
<h1><%= person %></h1>
// http://127.0.0.1:3000/form/able
// 輸出 able
-
將模板引擎用于 Express
- 在 Express 可以呈現模板文件之前,必須設置以下應用程序設置
- views:模板文件所在目錄。例如:app.set('views', './views') 默認
- view engine:要使用的模板引擎。例如:app.set('view engine', 'ejs')
8.使用模版引擎
app.get('/form/:name', function (req, res) {
// var person = req.params.name
var person = { age: 29, job: 'CEO', hobbies: ['eating', 'coding', 'finshing']}
res.render('form', { person: person })
})
app.get('/about', function (req, res) {
// var person = req.params.name
res.render('about')
})
<%- include('particals/header.ejs') -%> // 引用模版
<h1><%= person %></h1>
<h1><%= person.age %></h1>
<h2>hobbies</h2>
<ul> //遍歷數組
<% person.hobbies.forEach(function(item){ %>
<li>
<%= item %>
</li>
<% }) %>
</ul>
9.中間件介紹
-
中間件 (middleware)
- Express 是一個路由和中間件 Web 框架
- Express 應用程序基本上是一系列中間件函數調用
- 中間件介于 請求對象 (req)、響應對象 (res) 中間
- 可以有多個中間件
- 下一個中間件函數通常由名為 next 的變量來表示
- 如果當前中間件函數沒有結束請求/響應循環那么它必須調用 next(),以將控制權傳遞給下一個中間件函數。否則,請求將保持掛起狀態。
- 中間件作用
- 對請求和響應對象進行更改
- 結束請求或響應循環
- 調用堆棧中的下一個中間件函數
// 沒有路徑的中間件函數, 每次收到請求時執行該函數。
app.use(function (req, res, next) {
console.log('first middleware')
next() // 沒有響應請求,需要將控制權傳遞給下一個中間件函數
console.log('first middleware after next')
})
// 安裝在某個路徑的中間件函數
app.use('/m', function (req, res, next) {
console.log('second middleware')
res.send('ok')
})
// app.get('/m', function (req, res, next) {
// res.send('ok')
// })
- 內置中間件
- Express 中唯一內置的中間件函數是 express.static
- 負責提供 Express 應用程序的靜態資源
-
app.use(express.static('public'));
指定靜態資源根目錄 -
app.use('static', express.static('public'));
前綴目錄static/a.png
10.路由中間件
- 路由器層中間件綁定到 express.Router() 的實例
- 分離路由到子文件目錄中,最上次只調用,總分路由
// server.js
var indexRouter = require('./routes/index')
var usersRouter = require('./routes/users')
app.use('/', indexRouter)
app.use('/users', usersRouter)
// users.js
var express = require('express')
var router = express.Router()
// 這里注意,因為前面路由匹配到/users了,這里直接時根即可,二級目錄
router.get('/', function (req, res, next) {
res.send('users')
})
module.exports = router
11.項目實踐 part 1 項目搭建
- express-todolist 實踐項目
-
npm init -y
初始化 package.json -
npm install --save express body-parser ejs
安裝包
-
12.項目實踐 part 2 Controller
- 新建
controllers
文件夾,單獨存放控制器
//app.js
var express = require('express')
var todoController = require('./controllers/todoController')
var app = express()
app.set('view engine', 'ejs')
// 指定public目錄下為靜態文件根目錄
app.use(express.static('public'))
todoController(app)
app.listen(3000)
console.log('listening to port 3000')
// todoController.js
module.exports = function (app) {
app.get('/todo', function (req, res) {
})
app.post('/todo', function (req, res) {
})
app.delete('/todo', function (req, res) {
})
}
13.項目實踐 part 3 實現頁面
新建
views
文件夾,存放模版頁面,todo.ejs
-
使用 BootCDN 在線免費 jQuery 庫
https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js
14.項目實踐 part 4 實現功能
-
body-parser
處理 post 請求 -
ajax
異步處理提交和刪除
// 顯示添加表單和取出內容
<div id="todo-table">
<form action="">
<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>
var bodyParser = require('body-parser')
var urlencodeParser = bodyParser.urlencoded({ extended: false})
var data = [{item: 'get milk'}, {item: 'walk dog'}, {item: 'coding a'}]
module.exports = function (app) {
app.get('/todo', function (req, res) {
res.render('todo', { todos: data })
})
app.post('/todo', urlencodeParser, function (req, res) {
data.push(req.body)
res.json(data) // 回復結束響應,可以回復其它的
})
app.delete('/todo/:item', function (req, res) {
data = data.filter(function (todo) { // 返回為true的內容
return todo.item.replace(/ /g, "-") !== req.params.item
})
res.json(data)
console.log(data)
})
}
// ajax 處理點擊提交 和 刪除,異步處理
$(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();
}
});
});
});
15.項目實踐 part 5 MongoDB 和 mLab
-
使用 MongoDB 持久化數據
- nosql 非關系型的數據庫,沒有行列的概念,存儲的 json 格式數據,用js很方便讀取
- MongoDB 概念解析
- collection 數據庫表/集合
- document 數據記錄行/文檔
- primary key 主鍵,MongoDB自動將_id字段設置為主鍵
-
使用線上免費 MongoDB 數據庫 mLab
- Database-as-a-Service features
- MongoDB on AWS, Azure, or Google. It's this easy.
- 注冊,創建數據庫,創建數據庫用戶
- shell 連接
mongo ds020208.mlab.com:20208/todos -u <dbuser> -p <dbpassword>
- URI
mongodb://<dbuser>:<dbpassword>@ds020208.mlab.com:20208/todos
16.項目實踐 part 6 Mongoose
-
mongoose 用來操作數據庫
- a MongoDB object modeling tool designed to work in an asynchronous environment.
npm install mongoose --save
- 安裝,連接,定義 Schema、model ,規定數據類型一致
const mongoose = require('mongoose')
mongoose.connect('mongodb://able8:xx@ds020208.mlab.com:20208/todos')
// Schema 模式,規定數據類型
var todoSchema = new mongoose.Schema({
item: String // 字段名,字符串
})
//對應數據庫中的表
var Todo = mongoose.model('Todo', todoSchema)
// 添加一條數據
var itemOne = Todo({ item: 'buy flowers'}).save(function (err) {
if (err) throw err
console.log('item saved')
})
17.項目實踐 part 7 保持數據到 MongoDB
- 操作數據,讀取,添加,刪除
- 實踐測試 mLab 國內訪問太慢了, 簡單測試還可以
- 其他可選包 mongolass
app.get('/todo', function (req, res) {
Todo.find({}, function (err, data) {
if (err) throw err
res.render('todo', { todos: data })
})
})
app.post('/todo', urlencodeParser, function (req, res) {
var itemOne = Todo(req.body).save(function (err, data) {
if (err) throw err
res.json(data)
})
})
app.delete('/todo/:item', function (req, res) {
// data = data.filter(function (todo) { // 返回為true的內容
// return todo.item.replace(/ /g, "-") !== req.params.item
// })
Todo.find({item: req.params.item.replace(/ /g, '-')}).remove(function (err, data) {
if (err) throw err
res.json(data)
})
})