vue实战:电商后台管理系统

在bilibili上学习一个vue项目:https://www.bilibili.com/video/BV1KJ411U7ML?p=149
配套资源:
https://pan.baidu.com/s/1FX_1sz0Xj-0r1R_E12Qh1g
提取码: 8exy
联系项目代码:https://gitee.com/sicauliuyang/vue_shop

项目结构

在这里插入图片描述

  • dist:存放build后可以直接部署的代码

  • node_modules:项目按照的依赖等资源库

  • public:存放的静态资源都会被简单的复制,而不经过 webpack

  • components: 存放自定义的vue组件

在这里插入图片描述

  • plugins :插件

  • router.index.js:路由配置

  • mian-dev.js:开发全局js,用于配置引入依赖等

  • main-prod.js:部署运行全局js

  • .estlintr.js:estlin规范配置文件

  • babel.config.js:babel配置

  • package-lock.json:就是锁定安装时的包的版本号,并且需要上传到git,以保证其他人在npm install时大家的依赖能保证一致。

  • package.json:安装依赖的版本号等信息

  • vue.config.js:修改webpack配置

路由

路由配置主要在router.index.js中

  • 路由导航守卫控制访问权限

    在路由入口js文件中,配置路由导航访问控制权限功能。注意:需要在暴露该路由对象之前进行配置

// 挂载路由导航守卫
router.beforeEach((to, from, next) => {
	// to 将要访问的路径
	// from 代表从哪个页面跳转而来
	// next 是一个函数, 表示放行
	//      next() 放行 next('/') 强制跳转
	// 首页直接放行
	if (to.path === '/login') return next()
	// 获取token
	const tokenStr = window.sessionStorage.getItem('token')
	// token不为空,放行
	if (!tokenStr) return next('/login')next()
})
export default router
  • 动态渲染菜单数据并进行路由控制
<el-menu router>
	 <el-submenu :index="item.id + ''" v-for=“item in menus" :key="item.id">
		 <template slot="title">
		 	<span>{{item.authName}}</span>
		 </template>
		 <el-menu-item :index="'/' + subItem.path" v-for="subItem in item.children" :key="subItem.id" >
		 	<span slot="title">{{subItem.authName}}</span>
		 </el-menu-item>
	 </el-submenu>
</el-menu>
  • 路由懒加载

https://router.vuejs.org/zh/guide/advanced/lazy-loading.html

axios网络通信

  • 基本配置
// 引入axios库,用于通信
import axios from 'axios'
// 配置请求的根路径
axios.defaults.baseURL = 'http://127.0.0.1:8888/api/private/v1/'
// 给请求头添加Authorization
axios.interceptors.request.use(config => {
 //
 config.headers.Authorization = window.sessionStorage.getItem('token')
 return config
})
// 在response拦截器中,隐藏进度条
axios.interceptors.response.use(config => {
 return config
})
// 每一个this组件都可以通过this.$http来发起请求
Vue.prototype.$http = axios

整体布局

整体布局:先上下划分,再左右划分

token设置

  • 登陆成功后保存token

在登陆函数中,当登陆成功后,把服务器传过来的token保存到window对象中的sessionStorage中。并跳转到主页中

// 登录成功后需要将服务器端传过来的token保存到sessionStorage中
window.sessionStorage.setItem('token',res.data.token);
// 通过编程式导航跳转到后台主页,路由地址为/home
this.$router.push("/home");
  • P371 主页中的退出功能

电击退出按钮,清空token,返回登陆页

vue.config.js修改webpack的默认配置

module.exports = {
	 chainWebpack: config => {
	 config.when(process.env.NODE_ENV === 'production', config => {
		 // 配置项目发布时使用的全局js
		 config.entry('app').clear().add('./src/main-prod.js')
		 // 使用externals设置排除项
		 config.set('externals', {
		 vue: 'Vue',
		 'vue-router': 'VueRouter',
		 axios: 'axios',
		 lodash: '_',
		 echarts: 'echarts',
		 nprogress: 'NProgress',
		 'vue-quill-editor': 'VueQuillEditor'
		 })
		 // 使用html插件,声明一个isProd变量
		 config.plugin('html').tap(args => {
			 args[0].isProd = true
			 return args
		 })
	 })
	 config.when(process.env.NODE_ENV === 'development', config => {
		 // 配置项目开发时使用的全局js
		 config.entry('app').clear().add('./src/main-dev.js')
		 // 使用html插件,声明一个isProd变量
		 config.plugin('html').tap(args => {
			 args[0].isProd = false
			 return args
		 })
	 })
	 }
}

设置externals采用CDN

默认情况下,依赖项的所有第三方包都会被打包到js/chunk-vendors.******.js文件中,导致该js文件过大,可以通过externals排除这些包,使它们不被打包到js/chunk-vendors.******.js文件中

  1. 在vue.config.js设置排除项

如上代码

  1. 在public/index.html中添加CDN
<!-- nprogress 的样式表文件 -->
 <link rel="stylesheet" href="https://cdn.staticfile.org/nprogress/0.2.0/nprogress.min.css" />
 <!-- 富文本编辑器 的样式表文件 -->
 <link rel="stylesheet" href="https://cdn.staticfile.org/quill/1.3.4/quill.core.min.css" />
 <link rel="stylesheet" href="https://cdn.staticfile.org/quill/1.3.4/quill.snow.min.css" />
 <link rel="stylesheet" href="https://cdn.staticfile.org/quill/1.3.4/quill.bubble.min.css" />
 <!-- element-ui 的样式表文件 -->
 <link rel="stylesheet" href="https://cdn.staticfile.org/element-ui/2.8.2/theme-chalk/index.css" />
 <script src="https://cdn.staticfile.org/vue/2.5.22/vue.min.js"></script>
 <script src="https://cdn.staticfile.org/vue-router/3.0.1/vue-router.min.js"></script>
 <script src="https://cdn.staticfile.org/axios/0.18.0/axios.min.js"></script>
 <script src="https://cdn.staticfile.org/lodash.js/4.17.11/lodash.min.js"></script>
 <script src="https://cdn.staticfile.org/echarts/4.1.0/echarts.min.js"></script>
 <script src="https://cdn.staticfile.org/nprogress/0.2.0/nprogress.min.js"></script>
 <!-- 富文本编辑器的 js 文件 -->
 <script src="https://cdn.staticfile.org/quill/1.3.4/quill.min.js"></script>
 <script src="https://cdn.jsdelivr.net/npm/vue-quill-editor@3.0.4/dist/vue-quill-editor.js"></script>
 <!-- element-ui 的 js 文件 -->
 <script src="https://cdn.staticfile.org/element-ui/2.8.2/index.js"></script>

对应删除main.js中的引用

  1. 根据发布或开发判断是否引用CDN

为了使开发测试不收干扰

在vue.config.js中获取html插件,添加变量,在index.html中进行判断

<% if(htmlWebpackPlugin.options.isProd) { %>
<!-- nprogress 的样式表文件 -->
 <link rel="stylesheet" href="https://cdn.staticfile.org/nprogress/0.2.0/nprogress.min.css" />
 <!-- 富文本编辑器 的样式表文件 -->
 <link rel="stylesheet" href="https://cdn.staticfile.org/quill/1.3.4/quill.core.min.css" />
 <link rel="stylesheet" href="https://cdn.staticfile.org/quill/1.3.4/quill.snow.min.css" />
 <link rel="stylesheet" href="https://cdn.staticfile.org/quill/1.3.4/quill.bubble.min.css" />
 <!-- element-ui 的样式表文件 -->
 <link rel="stylesheet" href="https://cdn.staticfile.org/element-ui/2.8.2/theme-chalk/index.css" />
 <script src="https://cdn.staticfile.org/vue/2.5.22/vue.min.js"></script>
 <script src="https://cdn.staticfile.org/vue-router/3.0.1/vue-router.min.js"></script>
 <script src="https://cdn.staticfile.org/axios/0.18.0/axios.min.js"></script>
 <script src="https://cdn.staticfile.org/lodash.js/4.17.11/lodash.min.js"></script>
 <script src="https://cdn.staticfile.org/echarts/4.1.0/echarts.min.js"></script>
 <script src="https://cdn.staticfile.org/nprogress/0.2.0/nprogress.min.js"></script>
 <!-- 富文本编辑器的 js 文件 -->
 <script src="https://cdn.staticfile.org/quill/1.3.4/quill.min.js"></script>
 <script src="https://cdn.jsdelivr.net/npm/vue-quill-editor@3.0.4/dist/vue-quill-editor.js"></script>
 <!-- element-ui 的 js 文件 -->
 <script src="https://cdn.staticfile.org/element-ui/2.8.2/index.js"></script>
<% } %>

项目上线

  1. 通过node创建服务器
    在vue_shop同级创建一个文件夹vue_shop_server存放node服务器
    使用终端打开vue_shop_server文件夹,输入命令 npm init -y
    初始化包之后,输入命令 npm i express -S
    打开vue_shop目录,复制dist文件夹,粘贴到vue_shop_server中
    在vue_shop_server文件夹中创建app.js文件,编写代码如下:
// 导入express对象
const express = require('express')
const app = express()
app.use(express.static('./dist'))
// 开启8998监听
app.listen(8998,()=>{
 console.log("server running at http://127.0.0.1:8998")
})

开启gzip压缩

打开vue_shop_server文件夹的终端,输入命令:npm i compression -D
打开app.js,编写代码:

const express = require('express')
const compression = require('compression')
const app = express()
app.use(compression())
app.use(express.static('./dist'))
app.listen(8998,()=>{
 console.log("server running at http://127.0.0.1:8998")
})

配置https服务

配置https服务一般是后台进行处理,前端开发人员了解即可。
首先,需要申请SSL证书,进入https://freessl.cn官网 在后台导入证书,打开今天资料/素材,复制素材中的两个文件到vue_shop_server中
打开app.js文件,编写代码导入证书,并开启https服务

const express = require('express')
const compression = require('compression')
const https = require('https')
const fs = require('fs')
const app = express()//创建配置对象设置公钥和私钥
const options = {
 // 下载的证书文件
 cert:fs.readFileSync('./full_chain.pem'),
 key:fs.readFileSync('./private.key')
}
app.use(compression())
app.use(express.static('./dist'))
//启动https服务
https.createServer(options,app).listen(443)

注意:因为我们使用的证书有问题,所以无法正常使用https服务

使用pm2管理应用

打开vue_shop_server文件夹的终端,输入命令:npm i pm2 -g
使用pm2启动项目,在终端中输入命令:pm2 start app.js --name 自定义名称
查看项目列表命令:pm2 ls
重启项目:pm2 restart 自定义名称
停止项目:pm2 stop 自定义名称
删除项目:pm2 delete 自定义名称

Elment-ui 使用

  • 主页的布局

使用element-ui 的Container布局元素

这里需要引入对应的布局元素,去掉前面的el,去掉字母大写

el-container : Container

布局元素的class类,默认和名字相同 el-container 的一个类:el-container

  • 主页左侧菜单布局

使用NavMenu布局

  • 登录组件登录前的预验证

获取表单对象,并调用表单对象的validate方法,该方法有一个返回函数,其参数为一个布尔值,当验证为真时返回 true,否则返回false

this.$refs.loginFormRef.validate(valid => {
 //未通过验证
 if (!valid) return
 //通过验证
 })
  • 登录组件实现表单重置

获取表单对象,并调用表单对象的resetFields方法

  • 控制添加标签文本框的显示

$nextTick 的执行时机: DOM 更新完毕之后

<el-button size="small" v-else @click="showTagInput(scope.row)">+ New Tag</el-button>
showTagInput(row) {
 row.tagInputVisible = true
 // 当我们修改了 data 中 tagInputVisible 的值以后,如果要操作文本框,必须等页面重新渲染完毕之后才可以,所以,必须把操作文本框的代码放到 $nextTick 中,当作回调去执行($nextTick 的执行时机,是在 DOM 更新完毕之后)
 this.$nextTick(() => {
 this.$refs.saveTagInput.$refs.input.focus()
 })
}

积累

  • 时间过滤器
// 时间格式过滤器
Vue.filter('dateFormat', function (originVal) {
 // 获取时间对象
 const dt = new Date(originVal)
 // 年
 const y = dt.getFullYear()
 // 月 getMonth返回的是从0 开始的,所以需要加1;如果不是两位,在前面补0
 const m = (dt.getMonth() + 1 + '').padStart(2, '0')
 // 日
 const d = (dt.getDate() + '').padStart(2, '0')
 // 时
 const hh = (dt.getHours() + '').padStart(2, '0')
 // 分
 const mm = (dt.getMinutes() + '').padStart(2, '0')
 // 时
 const ss = (dt.getSeconds() + '').padStart(2, '0')
 // 'yyyy-mm-dd hh:mm:ss'
 return `${y}-${m}-${d}  ${hh}:${mm}:${ss}`
})
  • async和await操作
  1. async/await场景

这是一个用同步的思维来解决异步问题的方案,当前端接口调用需要等到接口返回值以后渲染页面时。

  1. 名词解释

async
async的用法,它作为一个关键字放到函数前面,用于表示函数是一个异步函数,因为async就是异步的意思, 异步函数也就意味着该函数的执行不会阻塞后面代码的执行,async 函数返回的是一个promise 对象。

await
await的含义为等待。意思就是代码需要等待await后面的函数运行完并且有了返回结果之后,才继续执行下面的代码。这正是同步的效果

login() {
 this.$refs.loginFormRef.validate(async valid => {
 if (!valid) return;
 const { data: res } = await this.$http.post('login', this.loginForm);
 if(res.meta.status == 200){
 console.log(res.meta.msg);
 }
 })
}

插件依赖

  • vue-table-with-tree-grid:树形表格
  1. 基本使用 https://github.com/MisterTaki/vue-table-with-tree-grid)

  2. 效果

在这里插入图片描述

  • 字符串分割为数组

    data.forEach(item => {
     	item.attr = item.attr.length === 0 ? [] : item.attr.split(' ')
     })
    
  • vue-quill-editor:富文本编辑器

基本使用:https://github.com/surmon-china/vue-quill-editor

  • lodash进行深拷贝

  • nprogress:进度条效果

使用:https://github.com/rstacruz/nprogress

//导入进度条插件
import NProgress from 'nprogress'
//导入进度条样式
import 'nprogress/nprogress.css'
.....
//请求在到达服务器之前,先会调用use中的这个回调函数来添加请求头信息
axios.interceptors.request.use(config => {
 //当进入request拦截器,表示发送了请求,我们就开启进度条
 NProgress.start()
 //为请求头对象,添加token验证的Authorization字段
 config.headers.Authorization = window.sessionStorage.getItem("token")
 //必须返回config
 return config
})
//在response拦截器中,隐藏进度条
axios.interceptors.response.use(config =>{
 //当进入response拦截器,表示请求已经结束,我们就结束进度条
 NProgress.done()
 return config
})
  • babel-plugin-transform-remove-console

项目发布时,移除其中console.*

在babel.config.js中配置

//项目发布阶段需要用到的babel插件
const productPlugins = []
//判断是开发还是发布阶段
if(process.env.NODE_ENV === 'production'){
 //发布阶段
 productPlugins.push("transform-remove-console")
}
module.exports = {
 "presets": [
 "@vue/app"
 ],
 "plugins": [
 [
 "component",
 {
 "libraryName": "element-ui",
 "styleLibraryName": "theme-chalk"
 }
 ],
 ...productPlugins
 ]
}
  • 10
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 12
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值