Vue开发一个电商全栈项目

文章目录

    • 1、需求分析
    • 2、项目搭建
      • 2.1、创建后台管理系统
      • 2.2、创建客户端APP
      • 2.3、创建服务端
    • 3、开发服务端接口
      • 3.1、连接数据库
      • 3.2、封装数据模块对象
      • 3.3、设计接口
      • 3.4、封装CRUD(封装好的可以直接拿出来用)
      • 3.5、 将来实现一个功能模块(上面理解,这个要会用)
      • 3.6、接口规范
        • 3.6.1、分类管理模块
        • 3.6.2、商品管理模块
        • 3.6.3、数据统计模块
    • 4、后台管理系统开发
      • 4.1、设计路由
      • 4.2、封装axios请求
      • 4.3、文件上传
        • 4.3.1、设计服务端文件上传接口
        • 4.3.2、设计前端上传组件
      • 4.4、富文本编辑器的使用
      • 4.5、封装ECharts图表组件

1、需求分析

当前开发的是一个电商全栈项目,技术选型:

  • 前端
    • 前台:Vue(框架) + Vue-Router(路由) + Vuex(用于本地的缓存处理,全局状态管理) + axios(请求) + Vant(组件库)
    • 后台:Vue(框架) + Vue-Router(路由) + Vuex(用于本地的缓存处理,全局状态管理) + axios(请求) ElementUI(组件库)
  • 后端(服务端):Node + Express + mongoose(链接数据库模块) + cors(解决跨域) + jwt(登录)

2、项目搭建

    注意:后台管理系统 与 APP 需要分开创建,因为在 `main.js` 中同时引入 element-ui 和 vant 组件库容易冲突。

2.1、创建后台管理系统

第一步:创建项目并安装依赖:

创建项目命令:vue create admin( 使用 vue create 命令创建项目,项目名为 admin)

  注意:创建项目时,后台管理系统选择history模式,选择y【 Use history mode for router? (Requires proper server setup for index fallback in production) (Y/n)】

进入项目文件夹 :cd admin

安装axios请求:cnpm i axios --save

安装组件库:cnpm i element-ui --save

安装Vuex 数据持久化:cnpm i vuex-persistedstate --save

   指令汇总(除创建项目外(需手动选择项),可全部复制,交给cmd 自动一步一步安装,最后一项需回车,或者复制上回车):vue create admin
   
cd admin
cnpm i axios --save
cnpm i element-ui --save
cnpm i vuex-persistedstate --save

第二步:精简项目(项目文件夹保留文件)

- public 静态资源目录
- src 
	- http 封装axios请求
	- components 封装公共组件
	- router 路由配置目录
	- store 状态管理目录
	- views 封装视图组件
	- App.vue 根组件
	- main.js 入口文件
- package.json

第三步:在 main.js 中引入组件库

import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';

Vue.use(ElementUI);

第四步:启动项目(端口 8080):

npm run serve

2.2、创建客户端APP

cmd返回上一级:cd ..

第一步:创建项目并安装依赖:

创建项目命令:vue create app( 使用 vue create 命令创建项目,项目名为 app)

  注意:创建项目时,app系统选择hash模式(地址带个中#),选择n【 Use history mode for router? (Requires proper server setup for index fallback in production) (Y/n)】

进入项目文件夹 :cd app

安装axios请求:cnpm i axios --save

安装组件库:cnpm i vant --save

安装Vuex 数据持久化:cnpm i vuex-persistedstate --save

  指令汇总(除创建项目外(需手动选择项),可全部复制,交给cmd 自动一步一步安装,最后一项需回车,或者复制上回车):vue create app

cd app
cnpm i axios --save
cnpm i vant --save
cnpm i vuex-persistedstate --save

第二步:精简项目(项目文件夹保留文件)

- public 静态资源目录
- src 
	- http 封装axios请求
	- components 封装公共组件
	- router 路由配置目录
	- store 状态管理目录
	- views 封装视图组件
	- App.vue 根组件
	- main.js 入口文件
- package.json

第三步:在 main.js 中引入组件库

import Vant from 'vant'
import 'vant/lib/index.css'

Vue.use(Vant)

第四步:启动项目(端口 8080):

npm run serve

2.3、创建服务端

cmd返回上一级:cd ..

第一步:创建项目并安装依赖:

先检查是否安装Express,查看版本号(安装了显示版本号,提示没有内部外部命令就是没有安装,需要进行下一步安装):express --version

全局安装Express项目生成器(只需要安装一次,类似于脚手架工具):cnpm i express express-generator -g

使用 express 命令创建项目,项目名为 server:express server

进入项目文件:cd server

初始化依赖(因为当前建完项目没有任何依赖):cnpm i

链接数据库模块:cnpm i mongoose --save

解决跨域:cnpm i cors --save

全局安装 nodemon 热启动:cnpm i nodemon -g

   指令汇总(除创建项目外(需手动选择项),可全部复制,交给cmd 自动一步一步安装,最后一项需回车,或者复制上回车):
express --version
cnpm i express express-generator -g
express server

cd server
cnpm i
cnpm i mongoose --save
cnpm i cors --save
cnpm i nodemon -g

第二步:精简项目

- public  静态资源目录
- db 用于管理数据连接的目录
- models 用于管理数据模块对象的目录
- crud 用于管理增删改查封装的目录
- routes 用于管理路由的目录
- views 视图模板引擎管理目录(可删除)
- app.js 入口文件
- package.json

第三步:配置跨域请求

app.js 入口文件中引入 cors 模块

var express = require('express');
var cors = require('cors'); // 引入 cors
//var app = express();
 
app.use(cors()) 
// 将 cors 模块注册到中间件中,必须在路由跳转之前配置
//app.use('/',indexRouter) ;
//app.use(',users',usersRouter) ;

第四步:配置 nodemon 启动

pageage.json 文件中配置 scripts 命令:

"scripts": {
    "start": "nodemon ./bin/www"
}

第五步:启动项目(端口 3000):

npm start

3、开发服务端接口

server文件中创建文件搭建目录
   ↓ server
    → db              //用于链接数据库
      → index.js
    → models          //模块 用于创建数据模型
    → crud            // 用于增删改查 缩写
      → index.js

3.1、连接数据库

第一步:在 db/index.js 中封装连接数据库的函数:

//引入mongoose
//下载地址~官网 : https://www.mongodb.com/
//   前端教程网:https://web1024.cn/tool
var mongoose = require('mongoose')

/**
 * 声明一个函数,用于连接数据库的函数
 */
function dbConnect(){
    // mongoose 是异步 返回一个 promise 对象
    // mongodb 协议链接数据库在哪台机器上,本机:localhost:27017 ;指定链接库的名字:eshop2
    mongoose.connect('mongodb://localhost:27017/eshop2',{
        //如果数据库中没有这个集合 将会自动创建
        useNewUrlParser: true,
        useUnifiedTopology: true
    //调用 方法接收连接成功之后
    }).then(()=>{
        console.log('数据库连接成功')
    }).catch(err=>{
        console.error('数据库连接失败', err)
    })
}
//函数抛出
module.exports = dbConnect

在MongoDBCompass.exe可视化中操作:
在这里插入图片描述

Vue开发一个电商全栈项目_第1张图片
Vue开发一个电商全栈项目_第2张图片
Vue开发一个电商全栈项目_第3张图片

第二步:在 app.js 入口文件中调用数据库连接方法:

//引入 db
var dbConnect = require('./db');

//调用方法
dbConnect();//连接数据库

第三步:启动服务

npm start

服务启动成功后,查看cmd 控制台是否输出了 “数据库连接成功” 的内容。

3.2、封装数据模块对象

models 目录下创建模型对象文件,

例如:我们要设计一个商品分类的模块,就创建 models/classify.js 文件,示例代码如下:

//引入
var mongoose = require('mongoose')

/**
 * 创建商品分类的模型对象
 */
let schema = new mongoose.Schema({ // schema 用于定义和数据库中字段相同的属性名称和数据类型
    name: String       //分类的名称name 属性  值是String类型
})
//Classify就是把数据库转换成js后拿到的一个对象,将来做增删改查操作
let Classify = mongoose.model('classifys', schema)
//抛出
module.exports = Classify

例如:我们要设计一个商品的模块,就创建 models/goods.js 文件,示例代码如下:

var mongoose = require('mongoose')

/**
 * 创建商品的模型对象
 */
let schema = new mongoose.Schema({ // schema 用于定义和数据库中字段相同的属性名称和数据类型
    title: String, //商晶标题
    price: Number, //商品价格
    guige: Array, //商品规格
    content: String, //商品详情
    state: {
        type: Number,  //Number类型 可以多条件设置 
        default: 1 //商品状态,1为上架,2为下架
    },
    hot: {
        type: Number,
        default: 1 //是 否为热销商品,1为普通商品,2为热销商品
    }
    //等等。。。
})
let Goods = mongoose.model('goods', schema)

module.exports = Goods

如果再创建其他模块,参考此步骤。

3.3、设计接口

此处以添加商品分类为例。

第一步:在 routes 目录下创建对应的路由文件,例如 classify.js,示例代码如下:

//对应 3.6.1 接口规范
//没有调用封装的crud,就会每次都要写
var express = require('express');
var router = express.Router();
var Classify = require('../models/classify');

//添加商品分类 /classify/add
router.post('/add', function(req,res){
    //接收参数
    let {name} = req.body

    //保存到数据库
    Classify.create({name}).then(result=>{
        if(result){
            //添加成功后的响应
            res.json({
                code: 200,  //自定义标识,不是状态码
                msg: '添加成标识功'
            })
        }else{
            res.json({
                code: 300,
                msg: '添加失败'
            })
        }
    }).catch(err=>{
        res.json({
            code: 400,
            msg: '添加时出现异常'
        })
    })
})

//修改分类
router.post('/update', function(req,res){
	let C = req.body
	if(!c._id){
		res.json({
			code:300,
			msg:'id参数不能为空!'
		})
		return
	}
	crud.update(Classify,{_id:c._id}, {name: c.name,no: c.no},res )
})

//删除分类
router.get('/de1' , function(req,res){
	let {_id} = req.query
	if(!_id){
		res.json({
			code:300,
			msg:'id参数不能为空!'
		})
		return
	}
	crud.del(Classify,{_id},res)
})

//分页查询
router.get('/find', function(req,res){
	//let {page,pagesize,kw,s} = req.query
	//let where = {}
	//if(kw){
	//	where = {name: {$regex: kw}}
	//}
	//let sort = {}
	//if(s == 1){
	//	sort = {no: -1}
	//}else if(s == 2){
	//	sort = {no: 1}
	//}
	//crud-find(classify,page, pegeSize,where,sart ,res)
	
	let {page,pagesize,sort = 1} = req.query   //sort 排序  1降序  2升序,有值的话按值,没值的话按默认值
	
	//s为排序的条件对象
	let s = {}
	if(sort == 1){
		s = {no: -1}
	}else if(sort == 2){
		s = {no: 1}
	}
	crud.find(Classify,page, pegeSize,{},s ,res)
})

//非分页查询
router.get('/query', function(req,res){
	let {sort = 1} = req.query   //sort 排序  1降序  2升序,有值的话按值,没值的话按默认值
	
	//s为排序的条件对象
	let s = {}
	if(sort == 1){
		s = {no: -1}
	}else if(sort == 2){
		s = {no: 1}
	}
	crud.query(Classify,{},s ,res)
})


module.exports = router;

Vue开发一个电商全栈项目_第4张图片

第二步:

app.js 入口文件引入路由,示例代码如下:

//引入路由文件
var classifyRouter = require('./routes/classify');
//配置一个路由
app.use('/classify', classifyRouter);

第三步:在 postmain 工具中测试路由是否可用:
在这里插入图片描述

# 请求的路由地址
http://localhost:3000/classify/add

# 请求参数
{
	"name": "男装"
}

# 添加成功的响应结果
{
	code: 200,
	msg: '添加成功'
}

Vue开发一个电商全栈项目_第5张图片
Vue开发一个电商全栈项目_第6张图片

3.4、封装CRUD(封装好的可以直接拿出来用)

公共方法,写一遍不用动直接就可以用
crud/index.js 中封装增删改查的方法,示例代码如下:

添加的功能方法:

/**
 * 用于添加数据的公共方法(文档注释 可以一键生成API文档 ,两个*加@ 是竹节)【服务端才有】
 * @param {*} model 数据模型对象
 * @param {*} params 要添加的数据对象
 * @param {*} res 响应对象
 */
function add(model,params,res){
    model.create(params).then(result=>{
        if(result){
            //添加成功后的响应
            res.json({
                code: 200,
                msg: '添加成功'
            })
        }else{
            res.json({
                code: 300,
                msg: '添加失败'
            })
        }
    }).catch(err=>{
        res.json({
            code: 400,
            msg: '添加时出现异常'
        })
    })
}

修改的公共方法:

/**
 * 用于修改的公共方法
 * @param {*} model 数据模型对象
 * @param {*} where 要修改的条件
 * @param {*} params 修改后的新对象
 * @param {*} res 响应对象
 */
function update(model,where,params,res){
	// 修改的时候传入两个条件(修改的条件,修改的值) 返回一个result
    model.updateOne(where,params).then(result=>{
    	//result 里面放的是修改结果的对象
    	//result里面有个对象 n ,n>0 证明修改成功了很多条,n是几就是几条
    	//else 就是修改失败
    	//catch 就是修改时出现异常
        if(result.n > 0){
            res.json({
                code: 200,
                msg: '修改成功'
            })
        }else{
            res.json({
                code: 300,
                msg: '修改失败'
            })
        }
    }).catch(err=>{
        res.json({
            code: 400,
            msg: '修改时出现异常'
        })
    })
}

删除的公共方法:

/**
 * 删除的公共方法
 * @param {*} model 数据模型对象
 * @param {*} where 要删除的条件
 * @param {*} res 响应对象
 */
function del(model,where,res){
    model.findOneAndDelete(where).then(result=>{
        if(result){
            //添加成功后的响应
            res.json({
                code: 200,
                msg: '删除成功'
            })
        }else{
            res.json({
                code: 300,
                msg: '删除失败'
            })
        }
    }).catch(err=>{
        res.json({
            code: 400,
            msg: '删除时出现异常'
        })
    })
}

分页查询公共方法:(与上面不分页查询按需要选其一即可)

/**
 * 用于分页查询的公共方法
 * @param {*} model 模型对象
 * @param {*} page 当前页码
 * @param {*} pageSize 每页条数
 * @param {*} where 查询条件
 * @param {*} sort 排序条件
 * @param {*} res 响应对象
 */
async function find(model,page,pageSize,where,sort,res){

    //判断page是否存在
    if(!page){
        page = 1
    }else{
        page = parseInt(page)
        if(isNaN(page)){ //非数字
            page = 1
        }else{ //是数字
            if(page < 1){
                page = 1
            }
        }
    }

    //判断pageSize是否为空
    if(!pageSize){
        pageSize = 10
    }else{
    	//默认每页10条,如果进行赋值,每页最低每5条换页,最多不超过30条换页
        pageSize = parseInt(pageSize)
        if(isNaN(pageSize)){ //非数字
            pageSize = 10
        }else{ //是数字
            if(pageSize < 5){
                pageSize = 5
            }else if(pageSize > 30){
                pageSize = 30
            }meyiye
        }
    }

    //计算总页数,总页数 = Math.ceil(总记录数 ÷ 每页条数)
    let count = 0
    await model.find(where).countDocuments().then(result=>{
        count = result
    })
   // await model.find(where).count().then(result=>{
    //    count = result
   // })
		//如果上一步还没执行完,就执行下一步,就会出错,所以要把异步变同步,所以要在上一步 和 执行查询操作 前面加上 await
		//总页数 totalPage 
    let totalPage = Math.ceil(count/pageSize)

    //判断当前页码是否大于总页数
    //如果一条都没有的话,count为0  所以totalPage也会为0(0/每页条数  还为0)
    if(totalPage > 0 && page > totalPage){
        page = totalPage
    }

    //skip查询的起始位置,起始位置 = (当前页码 - 1)× 每页条数
    let start = (page - 1)*pageSize

	//执行查询操作
	//跳过多少条  skip从哪里开始看   limit看多少条
    await model.find(where).sort(sort).skip(start).limit(pageSize).then(result=>{
        if(result && result.length > 0){
            res.json({
                code: 200,
                msg: '查询成功',
                data: result,
                page,
                pageSize,
                count,
                totalPage 
            })
        }else{
            res.json({
                code: 300,
                msg: '没有查询到数据',
                data: [],
                page,
                pageSize,
                count,
                totalPage 
            })
        }
    }).catch(err=>{
        res.json({
            code: 400,
            msg: '查询时出现异常'
        })
    })
}

非分页查询公共方法:(与下面分页查询按需要选其一即可)

/**
 * 用于分页查询的公共方法
 * @param {*} model 模型对象
 * @param {*} where 查询条件
 * @param {*} sort 排序条件
 * @param {*} res 响应对象
 */
function query(model,where,sort,res){
	model.query(where).sort(sort).then(result=>{
        if(result && result.length > 0){
            res.json({
                code: 200,
                msg: '查询成功',
                data: result
            })
        }else{
            res.json({
                code: 300,
                msg: '没有查询到数据',
                data: []
            })
        }
    }).catch(err=>{
        res.json({
            code: 400,
            msg: '查询时出现异常'
        })
    })
}

需要在 crud/index.js 文件中抛出以上函数:

module.exports = {
    add,        //添加
    update,    //修改
    del,       //删除
    find,    //分页查询
    query    //非分页查询
}

3.5、 将来实现一个功能模块(上面理解,这个要会用)

实现一个用户有关的模块 (模型对象,路由在app中的引用,封装好的,写完不用再改,唯一修改的就是,有新的功能写一个新的二级路由)
第一步:创建模型、在models文件下创建一个users.js模块
我们要设计一个用户模块,就创建 models/users.js 文件,示例代码如下:
(与其他模块不一样的地方,需要改的就是schema里面的属性;集合的名称 users 改成对应的以及抛出对象的名称)

//引入
var mongoose = require('mongoose')

/**
 * 创建用户的模型对象
 */
let schema = new mongoose.Schema({ // schema 用于定义和数据库中字段相同的属性名称和数据类型
    username: String ,       //用户的名称
    pwd: String             //用户密码
})
// users 将来数据库中叫的名字 最后一个字母必须s
let Users= mongoose.model('users', schema)
//抛出
module.exports = Users

第二步:创建路由、
routes文件下创建一个users.js文件

//通过 express 导入一个路由
var express = require('express');
var router = express.Router();

//抛出一个路由
module.exports = router;

app.js 入口文件引入路由,示例代码如下:

//引入路由文件
var usersRouter = require('./routes/users');
//配置一级路由
app.use('/users', usersRouter );//确定有没有引入成功,可以按住 Ctrl 鼠标放在 usersRouter 上呈现小手状,点击直接跳转到路由界面,能定位到,说明引入成功

第三步:功能接口,在routes/users.js中(如果其他模块直接改掉 Users 对应部分)

//var express = require('express');   这是第一步的内容保留,这里只是为了展示写入位置
//var router = express.Router();       这是第一步的内容保留,这里只是为了展示写入位置

//保存到数据库里面,导入Users
var Users = require('../models/users');
//存储数据库的方法全在 crud 里封装着
var crud = require('../crud');

//与crud里面对应
//添加用户 
	//通过 post 或 get , /users 后面 /add 找到这个方法
	//服务端路由,就是通过 url地址与一个 函数 之间的 映射
router.post('/add', function(req,res){
    //接收参数      只要是post请求  就用body封装
    let {username,pwd} = req.body
	//调用自己封装的方法 .add( 放现在操作的模型,添加的数据就是{username=username 直接写username, pwd=pwd直接写pwd },res响应)
	crud.add(Users,{username,pwd},res)  //可以按住 Ctrl 鼠标放在 add 上呈现小手状,点击直接跳转查看封装思维
	//或者写成
	//let user = req.body
	//crud.add(Users,user,res)
})

//修改用户
router.post('/update', function(req,res){
    //接收参数      只要是post请求  就用body
    //user  整个对象
    let user = req.body
    //数组里只有ID是唯一修改的条件
    crud.update(Users,{_id:user._id},{
    	username:user.username,
    	pwd:user.pwd
    },res)
})

//删除用户
router.get('/del',function(req ,res){ 
	let {_id} = req.query
	crud.del(Users,{_id},res) 
})

//分页查询
router.get('/find' , function(req,res){
	let {page,pageSize} = req.query
	//目前没有 查询条件, 排序    不需要  所以{}
	crud.find(Users,page,pageSize,{},{},res)
})

//module.exports = router;      这是第一步的内容保留,这里只是为了展示写入位置

3.6、接口规范

全局配置:

# 服务器IP与端口(根据实际更改)
baseURL: http://localhost:3000

3.6.1、分类管理模块

添加分类:

接口地址(路由,发请求):/classify/add

请求方法:POST

返回数据格式:JSON

请求参数:

参数名称 参数类型 是否必填 参数描述
name String 分类的名称
no Number 否,默认值0 分类的排序

响应参数:

参数名称 参数类型 参数示例 参数描述
code Number 200 自定义,请求的结果状态,200为成功,300为失败,400为服务端异常
msg String “添加成功” 请求的结果描述

修改分类:

接口地址(路由,发请求):/classify/update

请求方法:POST

返回数据格式:JSON

请求参数:

参数名称 参数类型 是否必填 参数描述
_id String 要修改的分类id
name String 分类的新名称
no Number 否,默认值0 分类的新排序

响应参数:

参数名称 参数类型 参数示例 参数描述
code Number 200 自定义,请求的结果状态,200为成功,300为失败,400为服务端异常
msg String “修改成功” 请求的结果描述

删除分类:

接口地址(路由,发请求):/classify/del

请求方法:GET

返回数据格式:JSON

请求参数:

参数名称 参数类型 是否必填 参数描述
_id String 分类的id

响应参数:

参数名称 参数类型 参数示例 参数描述
code Number 200 自定义,请求的结果状态,200为成功,300为失败,400为服务端异常
msg String “删除成功” 请求的结果描述

分页查询分类:

接口地址:/classify/find

请求方法:GET

返回数据格式:JSON

请求参数:

参数名称 参数类型 是否必填 参数描述
page Number 否,默认值1 当前页码
pageSize Number 否,默认值10 每页查询条数,最少5条,最多30条
sort Number 否,默认值1 按no字段的排序规则,1为降序,2为升序

响应参数:

参数名称 参数类型 参数示例 参数描述
code Number 200 请求的结果状态,200为成功,300为失败,400为服务端异常
msg String “查询成功” 请求的结果描述
data any [{name:’’,no:’’},{}] 请求成功返回的数据
page Number 1 当前访问的页码
pageSize Number 10 每页返回条数
count Number 2000 总记录数
totalPage Number 50 总页数

非分页查询所有分类:

接口地址:/classify/query

请求方法:GET

返回数据格式:JSON

请求参数:

参数名称 参数类型 是否必填 参数描述
sort Number 否,默认值1 按no字段的排序规则,1为降序,2为升序

响应参数:

参数名称 参数类型 参数示例 参数描述
code Number 200 请求的结果状态,200为成功,300为失败,400为服务端异常
msg String “查询成功” 请求的结果描述
data any [{name:’’,no:’’},{}] 请求成功返回的数据

3.6.2、商品管理模块

同上

3.6.3、数据统计模块

同上

4、后台管理系统开发

4.1、设计路由

router/index.js 中设计路由

import Vue from 'vue'
import VueRouter from 'vue-router'
import routes from './routes' //将路由的模块进行封装

Vue.use(VueRouter)


const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

export default router

router/routes.js 文件代码示例:

//路由对象
const routes = [
    {
        path: '/',
        component: ()=>import('@/views/Main'),
        redirect: '/home',   //默认到home
        children: [
            {
                path: '/home',   //控制台 数据统计
                component: ()=>import('@/views/Home')
            },
            {
                path: '/classify',  //分类管理
                component: ()=>import('@/views/Classify')
            },
            {
                path: '/goods/add',  //发布商品
                component: ()=>import('@/views/Goods/add.vue')
            },
            {
                path: '/goods/list/:state',   //当前的状态,1上架,2下架
                component: ()=>import('@/views/Goods/list.vue')
            }
        ]
    }
]

export default routes

Vue开发一个电商全栈项目_第7张图片

封装全局的前置守卫,router/beforeEach.js 文件代码示例:

import router from './index'

/**
 * 路由的前置守卫
 */
export default ()=>{
    router.beforeEach((to,from,next)=>{
        
        console.log('beforeEach...')
        next()
    })
}

全局守卫封装好之后,需要在 main.js 入口文件调用守卫方法:

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import beforeEach from './router/beforeEach' //导入全局守卫模块

Vue.use(ElementUI);
Vue.config.productionTip = false
beforeEach() //调用守卫方法

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

4.2、封装axios请求

创建 src/http/index.js 文件,代码示例如下:

var axios = require('axios')

//创建axios实例
var instance = axios.create({
    baseURL: 'http://localhost:3000'
})

//请求拦截
instance.interceptors.request.use(config=>{
    // console.log('请求拦截...',config)
    return config
},err=>{
    console.error('请求时异常', err)
    return
})

//响应拦截
instance.interceptors.response.use(res=>{
    //请求成功对响应数据做处理
    // console.log('响应拦截', res)
    return res //该返回对象会传到请求方法的响应对象中
},err=>{
    // 响应错误处理
    console.error('响应时异常', err)
    return
})

/**
 * 用于发送HTTP请求的方法
 * @param {*} option 发送请求的配置项
 * @returns 响应结果
 */
async function http({path,method,params}){

    let result

    //get、delete
    if(method == 'get' || method == 'delete'){
        await instance[method](path,{
            params
        }).then(res=>{
            result = res.data
        }).catch(err=>{
            result = err
        })
    }else if(method == 'post' || method == 'put' || method == 'patch'){
        await instance[method](path,params).then(res=>{
            result = res.data
        }).catch(err=>{
            result = err
        })
    }
    
    return result
}

export default http

main.js 文件中引入 http 模块:

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import http from './http' //引入 http 模块

Vue.prototype.$http = http //将http函数挂载到Vue的实例上

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

在组件中使用 http 模块:


4.3、文件上传

4.3.1、设计服务端文件上传接口

安装相关依赖

cnpm i multer --save

创建 routes/upload.js 路由文件,示例代码如下:

var express = require('express');
var router = express.Router();
var multer = require('multer');
var fs = require('fs');
var path = require('path');

 //使用表单上传
 var upload = multer({
    storage: multer.diskStorage({
      //设置文件存储位置
       destination: function(req, file, cb) {
         let date = new Date();
         let year = date.getFullYear();
         let month = (date.getMonth() + 1).toString().padStart(2, '0');
         let day = date.getDate();
         let dir = "./public/img/" + year + month + day;
   
         //判断目录是否存在,没有则创建
         if (!fs.existsSync(dir)) {
           fs.mkdirSync(dir, {
             recursive: true
           });
         }
   
         //dir就是上传文件存放的目录
         cb(null, dir);
       },
       //设置文件名称
       filename: function(req, file, cb) {
         let fileName = file.fieldname + '-' + Date.now() + path.extname(file.originalname);
         //fileName就是上传文件的文件名
         cb(null, fileName);
       }
    })
  })

//文件上传的路由
router.post('/img', upload.single("mainPic"), function(req,res){
    let file = req.file
    let path = file.path.replace('public',"")
    // console.log(path)
    res.json({
        file: path
    })
} )

module.exports = router;

app.js 入口文件中引入路由

var uploadRouter = require('./routes/upload');

app.use('/upload', uploadRouter);

服务端上传接口地址: http://localhost:3000/update/img

4.3.2、设计前端上传组件

前端以 elementui 为例。

使用 上传组件,示例代码如下:




4.4、富文本编辑器的使用

wangEditor 为例。

安装依赖

cnpm i wangeditor --save

在组件中引入



设置高度

// 设置编辑区域高度为 500px
editor.config.height = 500

设置菜单

// 默认情况下,显示所有菜单
editor.config.menus = [
    'head',
    'bold',
    'fontSize',
    'fontName',
    'italic',
    'underline',
    'strikeThrough',
    'indent',
    'lineHeight',
    'foreColor',
    'backColor',
    'link',
    'list',
    'todo',
    'justify',
    'quote',
    'emoticon',
    'image',
    'video',
    'table',
    'code',
    'splitLine',
    'undo',
    'redo',
]

配置上传图片

//配置服务器地址
this.editor.config.uploadImgServer = this.serverIP+"/upload/editor/img"
//配置文件上传的字段名
this.editor.config.uploadFileName = 'img'

//服务端返回的数据格式,非常重要!!!
res.json({
      errno: 0,
      data: [
          {
              url: "", //访问图片的地址
              alt: "",
              href: ""
          }
      ]
 })

配置上传图片后的自定义插入

//图片上传的钩子函数
this.editor.config.uploadImgHooks = {
    //图片上传成功并返回结果时执行,可以手动插入图片
    customInsert: (insertImgFn,result) => {
        console.log(result.file)
          
        //插入图片的函数,参数为要插入的图片地址(切记:要有服务端的IP!)  
        insertImgFn(result.file)
    }
}

4.5、封装ECharts图表组件

安装依赖

cnpm i echarts --save

创建图表组件,例如创建 src/components/EchartsAxis.vue 组件,示例代码如下:






API说明:

属性名 数据类型 默认值 描述
width String 600px 图表区域的宽度,单位px
height String 400px 图表区域的高度,单位px
type String line 图表的样式,支持line/bar
smooth Boolean false 当type属性为line时,该项有效,true为平滑线,false为折线
title String - 当前图表的标题
data Object - 必填,格式为 {key: Value}
align String auto 标题的位置,支持left/center/right/auto

你可能感兴趣的:(vue)