安装
首先安装 vue 及 vue-cli,随后安装 express 框架,新版本的 express 创建应用时还需要使用 express-generator,这里一并安装。
npm i -g vue
npm i -g @vue/cli
npm i -g express
npm i -g express-generator
初始化项目
使用 vue-cli 搭建前端框架,选择版本为 vue2 创建。
vue create vue-express-style
cd vue-express-style
npm run serve
访问 localhost:8080 地址,可以看到如下界面:
使用 express-generator 创建后端框架,并设置使用pug模板引擎。
express --view=pug express-style
// Mac OS 或 Linux 系统使用下面的命令创建应用, 或在命令前添加 sudo
DEBUG=express-style:* npm start
// Windows系统在cmd中使用下面的命令
set DEBUG=express-style:* & npm start
// Windows系统在PowerShell中使用下面的命令
$env:DEBUG='express-style:*'; npm start
访问 localhost:3000 地址可以看到如下界面:
开发
后端接口开发
在 express-style > routes 下创建 product.js 文件。
// product.js
var express = require('express');
var router = express.Router();
// 创建 get 接口
router.get('/', function (req, res, next) {
var data = {
code: 200,
data: {name: 'admin', pwd: 'admin'},
isSuccess: true,
msg: "请求成功"
}
res.json(data);
});
module.exports = router;
在 express-style 下找到 app.js 文件,添加内容:
var productRouter = require('./routes/product')
app.use('/product', productRouter)
// app.js 完整内容
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var productRouter = require('./routes/product')
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/product', productRouter)
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
重启项目,访问地址 localhost:3000/product 可见页面。
前端开发
vue中请求接口数据大部分情况下使用 axios 插件操作,所以先安装此插件,进行配置。
npm i axios
// main.js
import axios from 'axios' // 引入axios
Vue.prototype.$axios = axios; // 将axios挂载到vue原型上
在页面中添加 init 方法,使用 axios 访问接口。
<template>
<div class="hello">
<h1>{{ msg }}</h1>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
data(){
return {
msg: ''
}
},
mounted() {
this.init()
},
methods: {
init() {
let self = this;
this.$axios({
method: 'get',
url: '127.0.0.1:3000/product',
}).then(function (res) {
self.msg = res.data;
})
.catch(function (error) {
console.error(error);
})
}
}
}
</script>
注意:这种情况下请求 localhost:8080 是能够发起请求,并且被后端接口响应到的。但是由于 axios 这种请求是 跨域 的,基于 同源策略
同源策略会阻止一个域的javascript脚本和另外一个域的能容进行交互。同源(即指在同一个域)就是两个页面具有相同的协议(protocol)、主机(host)和端口号(port)。
问题解决
此刻访问 localhost:8080 模块可以看到请求处于跨域状态,无法获取到数据,我们需要在前端设置代理,解决跨域问题。
// main.js 添加
// 配置请求的根路径
axios.defaults.baseURL = '/api/'
// 挂载到原型对象之前 先设置拦截器 通过axios请求拦截器添加token,保证拥有获取数据的权限
axios.interceptors.request.use(config => {
// 为请求头对象添加Token验证的Authorization字段
config.headers.Authorization = window.sessionStorage.getItem('token')
// 最后都必须 return config
return config
})
axios.interceptors.response.use(config => {
return config
})
// vue.config.js
module.exports = {
// 项目部署的基础路径
// 我们默认你的应用将会部署在域名的根部,比如 https://www.xxx.com/
// 如果你的应用时部署在一个子路径下,那么你需要在这里指定子路径。
// 比如,如果你的应用部署在https://www.xxx.com/public/
// 那么将这个值改为 `/public/`
// 部署生产环境和开发环境下的URL:可对当前环境进行区分,baseUrl 从 Vue CLI 3.3 起已弃用,要使用publicPath
/* baseUrl: process.env.NODE_ENV === 'production' ? './' : '/' */
publicPath: process.env.NODE_ENV === 'production' ? '/public/' : './',
/* 输出文件目录:在npm run build时,生成文件的目录名称 */
outputDir: 'dist',
/* 放置生成的静态资源 (js、css、img、fonts) 的 (相对于 outputDir 的) 目录 */
assetsDir: "assets",
/* 是否在构建生产包时生成 sourceMap 文件,false将提高构建速度 */
productionSourceMap: false,
/* 默认情况下,生成的静态资源在它们的文件名中包含了 hash 以便更好的控制缓存,你可以通过将这个选项设为 false 来关闭文件名哈希。(false的时候就是让原来的文件名不改变) */
filenameHashing: false,
/* 代码保存时进行eslint检测 */
lintOnSave: true,
/* webpack-dev-server 相关配置 */
devServer: {
/* 自动打开浏览器 */
open: true,
/* 设置为0.0.0.0则所有的地址均能访问 */
host: '0.0.0.0',
port: 8080,
https: false,
hotOnly: false,
/* 使用代理 */
proxy: { // string | Object
'/api': {
/* 目标代理服务器地址 */
target: 'http://127.0.0.1:3000',
/* 允许跨域 */
changeOrigin: true,
pathRewrite: {
'^/api': '' //规定请求地址以什么作为开头
}
},
},
},
}
// HelloWorld.vue 修改之前的请求地址
this.$axios({
method: 'get',
url: '/product',
}).then(function (res) {
self.msg = res.data;
})
.catch(function (error) {
console.error(error);
})
重启前后端系统,访问 localhost:8080