手把手教你通过express框架搭建后台+vue框架搭建前台

若如初见. 提交于 2020-08-15 14:31:50

最近这两天有点闲,通过自研学习了如何使用express框架搭建后台以及vue框架开发前端。express框架是用来搭建web服务,是nodejs的二次封装。vue就是前端框架。那么可以通过搭建express框架用来写接口,vue框架写页面用来调用接口,形成全栈的开发。
1、搭建express过程
使用 express的脚手架快速搭建:express-generator

首先安装express 和express-generator
npm install  -g express,npm install -g express-generator(这是全局安装)
创建项目
express -e 目录
npm install 安装依赖
npm start 开启项目
安装后台热更新模块(这样方便开发,修改文件就不需要重启启动了,会热更新)
npm i nodemon --save(局部安装,下载到项目依赖,所以一定要进入项目目录里安装)
安装完成nodemon之后,需在package.json的**scripts**修改命令行:
"scripts": {
    "start": "nodemon ./bin/www"
  },
安装完成之后的项目结构目录
│  app.js
│  package-lock.json
│  package.json
│
├─bin
│      www
│
├─public
│  ├─images
│  ├─javascripts
│  └─stylesheets
│          style.css
│
├─routes
│      index.js
│      users.js
│
└─views
        error.jade
        index.jade
        layout.jade

以上就是完成对express脚手架的安装啦~~ 端口号3000。
接下来介绍一下app.js:

app.use(express.static(path.join(__dirname, 'public')));		//静态托管,在搭建大前端时将页面放置public文件夹。因为我们是前后端分离模式,所以可以把这行代码注释了
// view engine setup
 app.set('views', path.join(__dirname, 'views'));		
app.set('view engine', 'jade');//视图模板,在搭建大后端的时将模板放置views文件夹,因为我们是前后端分离模式,所以可以把这行代码注释了

2、搭建vue过程
通过@vue/cli脚手架完成前端的搭建,端口号是8081~~

安装@vue/cli,vue脚手架3
npm i @vue/cli
//可查看版本
@vue/cli -V
//创建项目
vue create 项目名

好啦~前后端的demo都已经完成了,那么现在要做的就是连接数据库,以及前端如何调用接口问题。这也是项目当中比较难的地方。
3、连接数据库的问题
(1)操作数据库
(2)下载数据库
(3) 安装navicat,用navicat操作管理数据库,点击连接,添加连接名(可随意)
连接数据库 填写数据库的ip以及用户名以及密码点击连接测试,连接成功可点确定。
(4)连接数据库,nodejs操作数据库写接口在项目中安装好mysql数据库驱动。





下载第三方包  mysql(相当于驱动包,依赖模块)
npm i mysql --save(项目依赖)
注意:安装mysql时最好是先cd到项目文件夹下,如果不这样的话必须全局安装,为避免无法找到mysql模块,还是在项目文件夹下安装较为保险。
//连接数据库的代码,新建sql文件夹,新建db.js文件

测试版本的连接数据库代码:
在这里插入图片描述
在这里插入图片描述
因为开发每一个接口都需要连接数据库,那么上面的代码就得在每个接口写一遍,为了不让代码冗余,进行封装。


let  mysql=require('mysql');
module.exports=(option={},sql,callback)=>{
	let host=option.host||'99.47.133.165';	//数据库所在的服务器的ip地址
	let user=option.user||'root';	//用户名
	let password=option.password||'3edc$RFV5tgb';	//密码
	let database=option.database ||null  		//你的数据库名
	let db=mysql.createConnection({
		host:host,
		user:user,
		password:password,
		database:database
	});		//创建连接
	if(!(typeof sql=='string')){
		return ;
	};
	db.connect();		//打开连接
	//数据库操作也是异步的
	db.query(sql,(error,result)=>{
		if(error){
			console.log(error);
			return;
		}
		callback(result);
	})
	//关闭连接
	db.end();
}

前端提供一个页面:
在这里插入图片描述

<template>
	<div class="login">
		<div class="content">
			<el-form :model="ruleForm" status-icon :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
				<el-form-item label="账号" prop="age">
					<el-input v-model.number="ruleForm.age"></el-input>
				</el-form-item>
				<el-form-item label="密码" prop="pass">
					<el-input type="password" v-model="ruleForm.pass" autocomplete="off"></el-input>
				</el-form-item>
				<el-form-item>
					<el-button type="primary" @click="submitForm('ruleForm')">登录</el-button>
					<el-button @click="resetForm('ruleForm')">注册</el-button>
				</el-form-item>
			</el-form>
		</div>
	</div>
</template>

<script>
	import axios from 'axios';
	export default{
		name:'loginPage',
		data(){
			var checkAge = (rule, value, callback) => {
        if (!value) {
          return callback(new Error('年龄不能为空'));
        }
        setTimeout(() => {
          if (!Number.isInteger(value)) {
            callback(new Error('请输入数字值'));
          } else {
            if (value < 18) {
              callback(new Error('必须年满18岁'));
            } else {
              callback();
            }
          }
        }, 1000);
      };
      var validatePass2 = (rule, value, callback) => {
        if (value === '') {
          callback(new Error('请再次输入密码'));
        } else if (value !== this.ruleForm.pass) {
          callback(new Error('两次输入密码不一致!'));
        } else {
          callback();
        }
      };
			return {
				 ruleForm: {
          pass: '',
          age: ''
        },
				rules: {
          pass: [
            { validator: validatePass2, trigger: 'blur' }
          ],
          age: [
            { validator: checkAge, trigger: 'blur' }
          ]
        }
      };
		},
		methods:{
			submitForm(){
				this.$api.request({
					methods:'get',
					url:'/api/user/login',
// 					params:{
// 						age:this.ruleForm.age,
// 						password:this.ruleForm.password,
// 					}
				}).then(res=>{
					console.log(res)
				}).catch(err=>{
					console.log(err)
				})
// 				axios.get('localhost:3000/user/login').then(res=>{
// 					console.log(res)
// 				})
			},
			resetForm(){},
		}
	}
</script>

<style lang="scss" scoped>
	.login{
			width: 100%;
			height: 100%;
			background: #ff14932e;
			.content{
				width: 400px;
				height: 400px;
				position: absolute;
				left: 0;
				right: 0;
				bottom: 0;
				top: 0;
				margin:auto;
			}
	}
</style>

后台express框架的app.js文件代码以及route文件夹下的users.js的代码

//在app.js写入如下代码行
app.use('/api/user/login', usersRouter);	//路由导向
//在文件route->users.js处理路由
var express = require('express');
var router = express.Router();
var db=require('../sql/db.js');
router.get('/', function(req, res, next) {
	console.log('dsdhh');	//如果调用成功就会打印
	res.send();
});

module.exports = router;

前端通过请求调用接口,后台打印结果,说明数据调用成功。
在这里插入图片描述
其实在连调的这个过程当中,还真遇到坑
坑1、跨域问题
Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension,Uncaught (in promise) Error: Network Error     at createError (createError.js?2d83:16)     at XMLHttp
解决跨域问题:
后台做配置,在app.js入口文件写如下代码。一定要在路由导向之前写





app.all("*",(req,res,next)=>{
    //设置允许跨域的域名,*代表允许任意域名跨域
    res.header("Access-Control-Allow-Origin",'http://localhost:8081');//火狐,360本地开发需要具体写前端的端口看,这是一个坑。
    res.header("Access-Control-Allow-Origin", "*");//谷歌浏览器写*就行
    //允许的header类型
    res.header("Access-Control-Allow-Headers", "X-Requested-With,Content-Type");Content-Type不加
    //跨域允许的请求方式 
    res.header("Access-Control-Allow-Methods","DELETE,PUT,POST,GET,OPTIONS");
		res.header("X-Powered-By","Express");
		res.header("Content-Type","application/json;charset=utf-8");
		res.header("Access-Control-Allow-Credentials",true)
//     if (req.method.toLowerCase() == 'options')
//       res.send(200);  //让options尝试请求快速结束
//     else
			next();
})

坑2:
在这里插入图片描述
路由找不到,路由导向的path要和接口的path一致,但是在route文件夹下写接口是要重定向。代码如下:

var express = require('express');
var router = express.Router();
var db=require('../sql/db.js');
router.get('/', function(req, res, next) {
	console.log('dsdhh');
	res.send();
});

module.exports = router;

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!