前端搭建
项目初始化
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 进行相应修改
- 删除 src/router/modules 文件夹
- 删除 src/vendor 文件夹
如果是线上项目,建议将 components 的内容也清理,以免影响访问速度,或者直接使用 vue-admin-template 构建项目
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 进行全局配置:
- title: 站点标题,进入某个页面后,格式为:页面标题-站点标题
title: '三味书屋',
- showSettings: 是否显示右侧悬浮配置按钮
- tagsView: 是否显示页面标签功能条
- fixedHeader: 是否将头部布局固定
- sidebarLogo: 菜单栏中是否显示 LOGO
- errorLog: 默认显示错误日志的环境
通过全局搜索可以看到 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 运行环境,它使得 Javascript 可以在服务端直接与操作系统进行交互,与文件控制,网络交互,进行控制等。
Chrome 浏览器同样是集成了 V8 引擎的 Javascript 运行环境,与 Node 不同的是它们向 Javascript 注入的内容不同 Chrome 向 Javascript 注入了 window 对象,Node 注入的是 global ,这使得两者应用场景完全不同,Chrome 的 Javascript 所有的指令都需要通过 Chrome 浏览器作为中介实现
Express |简介
express 是一个轻量级的 Node Web 服务端框架,同样是一个人气超高的项目,它可以帮助我们快速的搭建,基于 Node 的 Web 应用
项目初始化
创建项目目录 admin-demo-node,进入目录执行命令初始化项目
npm init -y
安装依赖
npm i -S express
创建 app.js
// 引用 express
const express = require('express')
// 创建 express 应用
const app = express()
// 监听 / 路径 get 请求
app.get('/',function(req,res){
// 通过 get 请求的时候会返回个客户端
res.send('hello node')
})
// 使 express 监听 5000 端口号发起的 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
执行命令启动
node app.js
浏览器输入 http://localhost:5000
Express 三大基础概念
中间件
中间件是一个函数,请求和响应周期中被顺序调用
写一个中间函数
调用中间件注意事项:
- next() 必须调用,否则不会向下执行,也就是说 执行完上上面的代码后,next() 下面的代码不会再执行了,会一直等待
- 一定要在发起请求之前调用,否则请求已经执行完毕,也不会去调用中间件
/**
* 写一个中间函数
* 调用中间件注意事项:
* 1. next() 必须调用,否则不会向下执行,也就是说 执行完上上面的代码后,
* next() 下面的代码不会再执行了,会一直等待
* 2. 一定要在发起请求之前调用,否则请求已经执行完毕,也不会去调用中间件
*/
const myLogger = function(req,res,next){
console.log('myLogger')
next()
}
// 通过 app.use() 使用中间件,和 vue 加载插件非常相似
app.use(myLogger)
路由
应用如何响应请求的一种规则
响应 / 路径的 get 请求
// 监听 / 路径 get 请求
app.get('/',function(req,res){
// 通过 get 请求的时候会返回个客户端
res.send('hello node')
})
响应 / 路径的 post 请求
// 监听 / 路径 post 请求
app.post('/',function(req,res){
res.send('post 请求')
})
规则主要分两部分
- 请求方法: get ,post ......
- 请求的路径:/ , /user, /*user$/......
异常处理
通过自定义异常处理中间件处理请求中产生的异常
// 异常处理中间件,它也是一个 function
app.get('/user',function(req,res){
throw new Error('这是故意抛出的异常')
})
// 注意参数一个都不能少否则,视为普通中间件
// 异常处理要放到请求之后调用
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)
使用时需要注意两点:
- 参数一个都不能少,否则会视为普通中间件
- 中间件需要在请求之后引用
浏览器输入 http://localhost:5000/user
后端框架搭建
路由
安装 boom 依赖,最大的好处是可以快速的帮我们生成一些异常信息
npm i -S boom
app.js
// 引用 express
const express = require('express')
// 应用我们自定义的中间件
const router = require('./router')
// 创建 express 应用
const app = express()
// 将我们自定义的全局路由,托管到自定义的 router 下进行处理
app.use('/',router)
// 使 express 监听 5000 端口号发起的 http 请求
const server = app.listen(5000,function(){
const {address,port} = server.address()
console.log('http Server is running on http://%s:%s',address,port)
})
创建 router 文件夹,创建 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()
// 监听根路径的处理
router.get('/',function(req,res){
res.send('欢迎学习三味书屋管理后台')
})
// 导出 router 主要作用帮我们来进行路由的监听
module.exports = router
创建 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
创建 router 文件夹,创建 router/constant.js
// 导出一个错误状态码
module.exports = {
CODE_ERROR: -1
}
启动,访问根路径 http://localhost:5000
app.js 引入 userRouter
// 通过 userRouter 来处理 /user 路由,对路由进行解耦
// 这里我们指定了路由的前缀 /user
router.use('/user',userRouter)
这里指定的路由的前缀 /user 所有访问路径前要加 /user
访问 http://localhost:5000/user/info
添加 404 异常处理
/**
* 集中处理 404 请求的中间件
* 注意:该中间件必须放在正常处理流程之后,否则会拦截正常请求
*/
router.use((req,res,next) => {
// 使用 next 其实是继续的将异常向下传递,应为后续可能还要加一些异常处理
next(boom.notFound('接口不存在'))
});
访问一个不存在的路径
添加我们自定义的异常中间件
自定义路由异常处理中间件
注意两点:
- 方法的参数不能少
- 方法必须放在路由最后
/**
* 自定义路由异常处理中间件
* 注意两点:
* 1. 方法的参数不能少
* 2. 方法必须放在路由最后
*/
router.use((err,req,res,next) => {
console.log(err)
/**
* 1. 首先获取 message ,message 就是我们上面自定义的 message,如果不存在返回一个“系统错误”
* 2. 去拿 statusCode ,statusCode 是从 output 里面拿,如果没有拿到默认返回的就是 500
* 3. 获取 errroMessage,仍然是从 output 中获取,playload 就是我们的参数,如果没有就返回 err.message
* 4. 最后通过 res.status 将错误码返回,返回错误码之后再返回一个 json ,json 中封装了我们的异常信息
*/
const msg = (err && err.message) || '系统错误'
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 的结果,方便前端做出处理
我们看一下 err 对象
data: null,
isBoom: true,
isServer: false,
output: {
statusCode: 404,
payload: { statusCode: 404, error: 'Not Found', message: '接口不存在' },
headers: {}
},
reformat: [Function],
typeof: [Function: notFound]
}