前端搭建
項目初始化
git clone https://gitee.com/panjiachen/vue-element-admin.git
cd vue-element-admin
npm i
npm run dev
成功訪問
項目精簡
- 刪除 src/views 下的源碼岭粤,保留:
dashboard: 首頁
error-page: 異常頁面
login: 登錄
redirect: 重定向 - 對 src/router/index 進(jìn)行相應(yīng)修改
- 刪除 src/router/modules 文件夾
- 刪除 src/vendor 文件夾
如果是線上項目,建議將 components 的內(nèi)容也清理老玛,以免影響訪問速度,或者直接使用 vue-admin-template 構(gòu)建項目
src/router/index 精簡完后
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
/* Layout */
import Layout from '@/layout'
export const constantRoutes = [
{
path: '/redirect',
component: Layout,
hidden: true,
children: [
{
path: '/redirect/:path(.*)',
component: () => import('@/views/redirect/index')
}
]
},
{
path: '/login',
component: () => import('@/views/login/index'),
hidden: true
},
{
path: '/auth-redirect',
component: () => import('@/views/login/auth-redirect'),
hidden: true
},
{
path: '/404',
component: () => import('@/views/error-page/404'),
hidden: true
},
{
path: '/401',
component: () => import('@/views/error-page/401'),
hidden: true
},
{
path: '/',
component: Layout,
redirect: '/dashboard',
children: [
{
path: 'dashboard',
component: () => import('@/views/dashboard/index'),
name: 'Dashboard',
meta: { title: 'Dashboard', icon: 'dashboard', affix: true }
}
]
}
]
/**
* asyncRoutes
* the routes that need to be dynamically loaded based on user roles
*/
export const asyncRoutes = [
// 404 page must be placed at the end !!!
{ path: '*', redirect: '/404', hidden: true }
]
const createRouter = () => new Router({
// mode: 'history', // require service support
scrollBehavior: () => ({ y: 0 }),
routes: constantRoutes
})
const router = createRouter()
// Detail see: https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465
export function resetRouter() {
const newRouter = createRouter()
router.matcher = newRouter.matcher // reset router
}
export default router
重新啟動 npm run dev
項目配置
通過 src/settings.js 進(jìn)行全局配置:
- title: 站點標(biāo)題择份,進(jìn)入某個頁面后厦酬,格式為:頁面標(biāo)題-站點標(biāo)題
title: '三味書屋',
- showSettings: 是否顯示右側(cè)懸浮配置按鈕
- tagsView: 是否顯示頁面標(biāo)簽功能條
- fixedHeader: 是否將頭部布局固定
- sidebarLogo: 菜單欄中是否顯示 LOGO
- errorLog: 默認(rèn)顯示錯誤日志的環(huán)境
通過全局搜索可以看到 src/utils/get-page-title.js 中引用了 全局的 title
import defaultSettings from '@/settings'
const title = defaultSettings.title || '三味書屋'
export default function getPageTitle(pageTitle) {
if (pageTitle) {
return `${pageTitle} - ${title}`
}
return `${title}`
}
get-page-title.js 在 src/permission.js 中被引用
Node 簡介
Node 是基于 V8 引擎的 Javascript 運行環(huán)境,它使得 Javascript 可以在服務(wù)端直接與操作系統(tǒng)進(jìn)行交互盼铁,與文件控制,網(wǎng)絡(luò)交互尝偎,進(jìn)行控制等饶火。
Chrome 瀏覽器同樣是集成了 V8 引擎的 Javascript 運行環(huán)境,與 Node 不同的是它們向 Javascript 注入的內(nèi)容不同 Chrome 向 Javascript 注入了 window 對象致扯,Node 注入的是 global 肤寝,這使得兩者應(yīng)用場景完全不同,Chrome 的 Javascript 所有的指令都需要通過 Chrome 瀏覽器作為中介實現(xiàn)
Express |簡介
express 是一個輕量級的 Node Web 服務(wù)端框架抖僵,同樣是一個人氣超高的項目鲤看,它可以幫助我們快速的搭建,基于 Node 的 Web 應(yīng)用
項目初始化
創(chuàng)建項目目錄 admin-demo-node,進(jìn)入目錄執(zhí)行命令初始化項目
npm init -y
安裝依賴
npm i -S express
創(chuàng)建 app.js
// 引用 express
const express = require('express')
// 創(chuàng)建 express 應(yīng)用
const app = express()
// 監(jiān)聽 / 路徑 get 請求
app.get('/',function(req,res){
// 通過 get 請求的時候會返回個客戶端
res.send('hello node')
})
// 使 express 監(jiān)聽 5000 端口號發(fā)起的 http 請求
const server = app.listen(5000,function(){
const {address,port} = server.address()
console.log('http Server is running on http://%s:%s',address,port)
})
啟動項目
修改 package.json
執(zhí)行命令啟動
node app.js
瀏覽器輸入 http://localhost:5000
Express 三大基礎(chǔ)概念
中間件
中間件是一個函數(shù)耍群,請求和響應(yīng)周期中被順序調(diào)用
寫一個中間函數(shù)
調(diào)用中間件注意事項:
- next() 必須調(diào)用义桂,否則不會向下執(zhí)行,也就是說 執(zhí)行完上上面的代碼后蹈垢,next() 下面的代碼不會再執(zhí)行了慷吊,會一直等待
- 一定要在發(fā)起請求之前調(diào)用,否則請求已經(jīng)執(zhí)行完畢曹抬,也不會去調(diào)用中間件
/**
* 寫一個中間函數(shù)
* 調(diào)用中間件注意事項:
* 1. next() 必須調(diào)用溉瓶,否則不會向下執(zhí)行,也就是說 執(zhí)行完上上面的代碼后,
* next() 下面的代碼不會再執(zhí)行了嚷闭,會一直等待
* 2. 一定要在發(fā)起請求之前調(diào)用,否則請求已經(jīng)執(zhí)行完畢赖临,也不會去調(diào)用中間件
*/
const myLogger = function(req,res,next){
console.log('myLogger')
next()
}
// 通過 app.use() 使用中間件胞锰,和 vue 加載插件非常相似
app.use(myLogger)
路由
應(yīng)用如何響應(yīng)請求的一種規(guī)則
響應(yīng) / 路徑的 get 請求
// 監(jiān)聽 / 路徑 get 請求
app.get('/',function(req,res){
// 通過 get 請求的時候會返回個客戶端
res.send('hello node')
})
響應(yīng) / 路徑的 post 請求
// 監(jiān)聽 / 路徑 post 請求
app.post('/',function(req,res){
res.send('post 請求')
})
規(guī)則主要分兩部分
- 請求方法: get ,post ......
- 請求的路徑:/ , /user, /*user$/......
異常處理
通過自定義異常處理中間件處理請求中產(chǎn)生的異常
// 異常處理中間件,它也是一個 function
app.get('/user',function(req,res){
throw new Error('這是故意拋出的異常')
})
// 注意參數(shù)一個都不能少否則兢榨,視為普通中間件
// 異常處理要放到請求之后調(diào)用
const errorHandler = function(err,req,res,next){
console.log('errorHandler......')
res.status(500).json({
error: -1,
msg: err.toString()
})
res.send('down......')
}
// 使用中間件
app.use(errorHandler)
使用時需要注意兩點:
- 參數(shù)一個都不能少嗅榕,否則會視為普通中間件
- 中間件需要在請求之后引用
瀏覽器輸入 http://localhost:5000/user
后端框架搭建
路由
安裝 boom 依賴,最大的好處是可以快速的幫我們生成一些異常信息
npm i -S boom
app.js
// 引用 express
const express = require('express')
// 應(yīng)用我們自定義的中間件
const router = require('./router')
// 創(chuàng)建 express 應(yīng)用
const app = express()
// 將我們自定義的全局路由吵聪,托管到自定義的 router 下進(jìn)行處理
app.use('/',router)
// 使 express 監(jiān)聽 5000 端口號發(fā)起的 http 請求
const server = app.listen(5000,function(){
const {address,port} = server.address()
console.log('http Server is running on http://%s:%s',address,port)
})
創(chuàng)建 router 文件夾凌那,創(chuàng)建 router/index.js
// 引入 express
const express = require('express')
// 引入 boom
const boom = require('boom')
// 引入自定義的 router
const userRouter = require('./user')
const {
CODE_ERROR
} = require('../utils/constant')
// 注冊路由 通過 Router() 的實例化,完成一個 router 的注冊
const router = express.Router()
// 監(jiān)聽根路徑的處理
router.get('/',function(req,res){
res.send('歡迎學(xué)習(xí)三味書屋管理后臺')
})
// 導(dǎo)出 router 主要作用幫我們來進(jìn)行路由的監(jiān)聽
module.exports = router
創(chuàng)建 router/user.js
// 引入 express
const express = require('express')
const router = express.Router()
router.get('/info',function(req,res,next){
res.json('user info ...')
})
module.exports = router
創(chuàng)建 router 文件夾吟逝,創(chuàng)建 router/constant.js
// 導(dǎo)出一個錯誤狀態(tài)碼
module.exports = {
CODE_ERROR: -1
}
啟動帽蝶,訪問根路徑 http://localhost:5000
app.js 引入 userRouter
// 通過 userRouter 來處理 /user 路由,對路由進(jìn)行解耦
// 這里我們指定了路由的前綴 /user
router.use('/user',userRouter)
這里指定的路由的前綴 /user 所有訪問路徑前要加 /user
訪問 http://localhost:5000/user/info
添加 404 異常處理
/**
* 集中處理 404 請求的中間件
* 注意:該中間件必須放在正常處理流程之后块攒,否則會攔截正常請求
*/
router.use((req,res,next) => {
// 使用 next 其實是繼續(xù)的將異常向下傳遞励稳,應(yīng)為后續(xù)可能還要加一些異常處理
next(boom.notFound('接口不存在'))
});
訪問一個不存在的路徑
添加我們自定義的異常中間件
自定義路由異常處理中間件
注意兩點:
- 方法的參數(shù)不能少
- 方法必須放在路由最后
/**
* 自定義路由異常處理中間件
* 注意兩點:
* 1. 方法的參數(shù)不能少
* 2. 方法必須放在路由最后
*/
router.use((err,req,res,next) => {
console.log(err)
/**
* 1. 首先獲取 message ,message 就是我們上面自定義的 message,如果不存在返回一個“系統(tǒng)錯誤”
* 2. 去拿 statusCode 囱井,statusCode 是從 output 里面拿驹尼,如果沒有拿到默認(rèn)返回的就是 500
* 3. 獲取 errroMessage,仍然是從 output 中獲取,playload 就是我們的參數(shù)庞呕,如果沒有就返回 err.message
* 4. 最后通過 res.status 將錯誤碼返回新翎,返回錯誤碼之后再返回一個 json ,json 中封裝了我們的異常信息
*/
const msg = (err && err.message) || '系統(tǒng)錯誤'
const statusCode = (err.output && err.output.statusCode) || 500
const errorMsg = (err.output && err.output.payload && err.output.payload.error) || err.message
res.status(statusCode).json({
code: CODE_ERROR,
msg,
error: statusCode,
errorMsg
})
})
訪問一個不存在的路徑時住练,會返回一個 json 的結(jié)果地啰,方便前端做出處理
我們看一下 err 對象
data: null,
isBoom: true,
isServer: false,
output: {
statusCode: 404,
payload: { statusCode: 404, error: 'Not Found', message: '接口不存在' },
headers: {}
},
reformat: [Function],
typeof: [Function: notFound]
}