这只是简单配置前后端,没有处理错误,也没有做好模块化
后面会完善,这是作为入门,了解前后端通信的整体流程
一、创建前端项目
- 在我们要放项目的文件夹中运行git或命令行
git clone https://github.com/PanJiaChen/vue-admin-template.git
- 不需要特地新建一个文件夹存克隆项目,生成的就是一个文件夹,可以重命名。
- 关于vue、vue-cli和vue-element-admin这里不细讲,有兴趣的,可以看他们的官方文档和github
- 克隆好后,进入文件夹,安装依赖
cnpm i - 启动项目
npm run dev - 这样就创建好我们的前端项目啦(空壳)
二、创建Koa服务器
1、在根目录创建server文件夹
没错,目录结构将会是这样子,
src前端项目与server后端项目在同一级当中
2、初始化server项目
不要急,前期的准备还是挺多的,本文也以后端入门为主
在server文件夹中运行命令行
npm init
- 注意:不是我们上传代码是初始化项目的
git init - 运行成功之后,会在server文件夹中生成一个
package.json的文件(主要用于自定义启动服务器和依赖包管理)
3、安装koa相关依赖
关于koa2我们在其他地方讲
cnpm i --save-dev koa koa-bodyparser koa-router
- 这里只安装了演示用的
koa依赖,实际上还需要安装很多相关依赖
koa
koa-router
koa-bodyparser
...
4、配置基础服务器并测试
安装好了依赖,就引入并调用试试吧
- 在
server文件夹中新建index.js
const Koa = require('koa') // 引入koa类,注意要大写(是个类class)
const bodyParser = require('koa-bodyparser') // 引入post请求解析
const router = require('koa-router')() // 引入post请求解析
const app = new Koa() // 实例化Koa
//调用路由模块的get/post等方法(路径,异步回调方法)
router.get('/', async (ctx, next) => {
// todo
})
app.use(bodyParser()) // 调用kao实例的use方法(插入中间件-堆积木)
app.use(router.routes()) // 调用use堆积木,传入路由模块的routes方法
app.listen(9000)
console.log('app start at port 9000...')
- 这里有一个小插曲,对
koa-router模块的引入产生了好奇require('koa-router')() - 看它的github库,看到官方的调用方法是
const Router = require('koa-router')
const router = new Router()
app.use(router.routes())
- 我:???这是class类???class类能用
require('koa-router')()这种方式跳过new???
- 不对啊,像
koa这个引入就只能使用new这个类才能调用 - 于是去github的源码找
koa-router暴露的是什么
1).关于new构造函数
- 暴露的是一个对象函数,即在该函数上设置原型属性、方法等。
- 调用可以跟普通函数一样调用并后面用
.再跟一个方法 - 也可以用
new把这个函数当成构造函数实例化成一个对象,用.跟一个方法
2).启动服务器
不管小插曲,只要我们用好koa提供的路由,配置koa实例的端口,就能启动服务器了
node index
- 命令行输出
app start at port 9000... - 浏览器访问
http://localhost:9000也不会出现无法访问此网站了
三、优化服务器编写
写过
vue或者其他前端项目的我们都知道,ES6、ES7的很多命令是非常方便且语义化的
但是node10x到目前为止,支持了许多ES6语法,却依旧没有支持import/export
我们又想像src文件夹里前端一样用到ES6的话,就可以引入和配置babel啦。(前端webpack也是用这个模块来支持es6的)
1、安装Babel7相关依赖
与网上大部分教程不同,这是最新的babel7,相关内容参考这篇博客
cnpm i --save-dev @babel/node @babel/core @babel/preset-env
2、配置Babel7文件
- 在
server文件夹中新建.babelrc文件
{
"presets": [
[
"@babel/preset-env",
{
"targets": {
"node": "current"
}
}
]
]
}
编译并启动服务器
babel-node index
或者
npx babel-node index
3、安装自动重启服务器依赖
用过vue或者其他前端的人都知道,我们保存代码,项目会帮我们重新启动渲染,不需要手动去关闭再重启(改了配置文件除外如:config文件夹)
cnpm i --save-dev nodemon
-
nodemon依赖模块,是命令行工具,我们可以使用nodemon index代替node index - 但是我们还要运行
babel运行编译啊,当然nodemon可以让我们自定义,监听什么运行什么命令行
nodemon -w index --exec babel-node index
-w ——监听(接文件路径或文件夹)
--exec ——监听到变化后执行(后接要执行的命令)
4、配置简写nodemon、babel命令行
我们都知道
webpack中的package.json能让我们通过npm run dev或者npm start等命令行执行操作
- 其实这些命令行都可以在
package.json中自定义配置
"scripts": {
"start": "nodemon -w index --exec babel-node index"
}
- 这样我们就能使用
npm start简写我们的合并了nodemon和babel的命令行了
四、创建mongoDB数据库
mongoDB不是简单安装依赖就可以的,它需要像
node一样下载安装,并且还要配置
这里就不讲解安装MongoDB了,讲了也可能会过时,网上有很多教程
1、安装mongoose框架依赖
mongoose是
MongoDB的封装后便于对数据操作的框架
cnpm i --save-dev mongoose
2、连接数据库
mongoose.connect('mongodb://localhost/testDB') // 连接或创建testDB数据库
- 与MongoDB原生指令相同,没有此数据库
testDB时会创建(有内容的话)
3、创建Schema(模式)
// 创建数据库的表头实例
var UserSchema = new mongoose.Schema({
username: String,
password: String,
email: String
})
- Schema(模式)是个实例类,我这里理解为表格的表头
4、创建model
// 创建数据库的空表格
var User = mongoose.model('User', UserSchema) // 传入表格名、表头
- model,我这里理解为一个空表格
5、创建数据变量,并写入空表格
// 手造表格User的数据变量
var user = {
username: '123',
password: '123',
email: ''
}
var newUser = new User(user) // 写入表格数据,要new
- new 空表格,传入数据
6、更新数据库表格
newUser.save() // 更新表格
五、开启服务器连接数据库
好了,我们现在终于把,
数据库和服务器都准备好了服务器编写路由,查询输出数据库吧
1、编写路由,连接数据库
router.get('/', async(ctx, next) => {
const data = await User.findOne({ username: '123' }) // 调用表格的查找方法
const result = { // 创建响应返回的数据结构
code: 200,
response: data,
ts: 12345
}
ctx.response.body = result // 直接把响应写进页面
return result // return干嘛,return到network吗?
})
- 注意:
mongoose把表格方法包装成了promise,所以使用await - 注意:表格方法直接使用,上文数据库中
User实例(表格)(不是new后的,2者原型不一样)
2、启动服务器并打开访问
npm start
- 报错了,数据库连接失败
- 找到问题是,
mongoose连接的命令要传多一个参数
mongoose.connect('mongodb://localhost/testDB', { useNewUrlParser: true })
再次启动,命令行里就没有报错了
查看一下数据库
- 使用cmd的命令行,进入到mongodb的bin目录,运行:
mongo
- 这是打开数据库
- 再执行如下命令,逐层查看数据库的内容,
testDB是否有内容
到浏览器访问服务器相应的路由试试
六、前端获取服务器的数据
到上面,服务器成功开启,访问也成功连接到数据库
我们可以在前端通过axios来连接后端了
1、页面中尝试axios连接后端
-
vue-element-admin这个模版中,已经安装好axios依赖了 - 到
src文件夹中选择一个页面,这里选择首次进入的登录页面进行操作 - 如果之前登录过的,会跳过登录页面进入主页面,这时可以清楚cookie帐号缓存,也可以选择在主页面操作
- 选择
src --> view --> login --> index.vue文件
created(){
test() {
const res = await axios.get('http://localhost:9000')
if (res) console.log(res)
else console.log('接口没有请求到或者没有数据')
}
}
- 这是生命周期钩子函数,本篇文章不讲解
vue - 运行前端(同时后端server文件夹也要
npm start)
npm run dev
- 前端页面能显示,但是我们打开调控台
- 理所当然的,会出现跨域问题,前端端口是
9528,后端是9000
2、前端解决跨域问题
配置代理即可(原理查一下,很多总结)
- 选择
config --> index.js文件
proxyTable: {
'/api': {
target: 'http://localhost:9000',
changeOrigin: true,
pathRewrite: {
'^/api': ''
}
}
}
-
src --> view --> login --> index.vue文件
created(){
test() {
const res = await axios.get('/api')
if (res) console.log(res)
else console.log('接口没有请求到或者没有数据')
}
}
- 重启前端
npm run dev
- 有数据返回了,激动.jpg
3、后端解决跨域问题
-
server --> index.vue文件
import cors from 'koa2-cors' // 引入跨域
// 处理跨域的配置
app.use(cors({
exposeHeaders: ['WWW-Authenticate', 'Server-Authorization', 'Date'],
maxAge: 100,
credentials: true,
allowMethods: ['GET', 'POST', 'OPTIONS'],
allowHeaders: ['Content-Type', 'Authorization', 'Accept', 'X-Custom-Header', 'anonymous'],
}))
- 注意:这里有个坑
-
app.use(cors....)这个一定要在app.use(..)这些中间件的最前面 - 参考这里
- 前端后端,只需要一方配置跨域即可。这里测试的时候记得注释再试另一种
七、总结
- 我们实现了前后端通信的所有流程,但是整个过程十分简陋
- 服务器端的所有内容都在index.js里,没有模块化拆分
- 调用也仅仅做了get请求,并且数据库没有进行判断筛选需要哪些数据
- 后续将在这个入门教程中,继续工程化,优化成一个真正像项目的项目
- 所以本文主要用于熟悉前后端通信的整个大致流程
此文章的练习代码分支
参考博客(掘金)
vue-element-admin文档
koa2文档
mongoDB文档
mongoose文档
如有建议和疑问可联系
QQ:1017386624
邮箱:[email protected]