# admin-vue **Repository Path**: echoc/admin-vue ## Basic Information - **Project Name**: admin-vue - **Description**: 后端管理系统 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-08-05 - **Last Updated**: 2021-11-12 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## 电商后台管理系统(前端项目) ### 功能 > 管理用户账号,商品分类,商品信息,订单,数据统计等业务功能 ### 技术栈 - **_Vue全家桶_** 通过 Vue-CLI3 初始化生成。 - **_ElementUI_** 魔改样式。 - **_Less_** (CSS 预处理器) - **_screenfull_** (全屏插件) - **_Axios_** 网络请求 - **_Echarts_** 动态图标渲染 ### 项目初始化 + 安装Vue脚手架 + 通过Vue-Cli创建项目 + 配置Vue-router + 路由导航守卫控制访问权限 > 如果用户没有登录即没有token,则不能通过URL访问除login之外的页面(详细配置可查Vue-router官方文档) ```js //为路由对象,添加beforeEach导航守卫 router.beforeEach((to,from,next) => { //如果用户访问的登录页,直接放行 if (to.path === 'login') return next() //从sessionStorage中获取到保存的token值 const tokenStr = window.sessionStorage.getItem('token') //如果么有token,强制跳转到登录页 if(!tokenStr) return next('/login') next() }) ``` + 配置Element-UI 组件库 + 配置Axios库 + 增加相应拦截器,请求拦截器 ```js // axios请求拦截 axios.interceptors.request.use(config => { // 为请求头对象,添加token验证的Authorization字段 config.headers.Authorization = window.sessionStorage.getItem('token') return config }) ``` + 初始化git仓库 ### 项目依赖 1. 运行依赖 - axios => 发送请求 - echarts => 图表 - element-ui => element ui组件 - lodash => js工具库,该项目用到深拷贝与对象合并 - moment => 时间处理工具库 - nprogress => 进度条库 - v-viewer => 图片预览工具库 - vue-quill-editor => 富文本编辑器 - vue-table-with-tree-grid => 树形菜单/表格 2. 开发依赖 - babel => es6+语法转换 - eslint/babel-eslint => 语法检查 - less/less-loader => less语法 - babel-plugin-transform-remove-console => 移除console插件 ### Screenshots ![image-20210817230741534](/images/Snipaste_2021-08-18_00-01-19.png) ![image-20210817230741534](/images/Snipaste_2021-08-18_00-01-49.png) ![image-20210817230741534](/images/Snipaste_2021-08-18_00-02-04.png) ![image-20210817230741534](/images/Snipaste_2021-08-18_00-02-13.png) ![image-20210817230741534](/images/Snipaste_2021-08-18_00-12-20.png) ### 项目优化 #### 项目优化策略 + 生成打包报告 + 通过命令行参数形成生成报告 `vue-cli-service build --report` > --report选项可以生成report.html以分析包内容 + 通过vue ui控制台和可视化面板直接查看报告 + 添加**_nprogress_**进度条插件 + 添加**_screenfull_**全屏插件 + 编译项目去掉所有console.log打印日志 _**babel-plugin-transform-remove-console**_ + 通过vue.config.js修改webpack的默认配置 > 通过vue-cli 3.0工具生成的项目,隐藏了所有的webpack的配置项,目的是为了屏蔽项目的配置过程,让程序员把工作的重心,放到具体功能和业务逻辑的实现上 + 为开发模式与发布模式指定不同的打包入口 > 默认情况下,Vue项目的开发模式和发布模式,共用同一个打包的入口文件(即main.js)。为了让项目的开发和发布分离,我们可以各自指定打包的入口文件 > > 1. 开发模式入口文件 src/main-dev.js > 2. 发布模式入口文件 src/main-prod.js > > 方案:configureWebpack(通过链式编程形式)和chainWebpack(通过操作对象形式) > > 两种用法效果相同,只是用法不同。 > > 在vue.config.js导出的配置文件中,新增configureWebpack或chainWebpack节点,来自定义webpack的打包配置 ```js // 代码示例 module.exports = { chainWebpack: config => { // 发布模式 config.when(process.env.NODE_ENV === 'production', config => { config.entry('app').clear().add('./src/main-prod.js') }) // 开发模式 config.when(process.env.NODE_ENV === 'development', config => { config.entry('app').clear().add('./src/main-dev.js') }) } } ``` + 开启第三方库CDN(通过externals加载) > 默认情况下,通过import语法导入的第三方依赖包,最终会被打包合并到同一个文件中,从而导致打包成功后,单文件体积过大的问题 > > 为了解决上述问题,可以通过webpack的externals节点,来配置加载外部的cdn资源,凡是声明在externals中的第三方依赖包,都不会被打包 1. 在vue.config.js写入externals节点配置项 ```js module.exports = { devServer: { port: 8555, open: true }, chainWebpack: config => { // 发布模式 config.when(process.env.NODE_ENV === 'production', config => { config.entry('app').clear().add('./src/main-prod.js') }) config.set('externals', { vue: 'Vue', axios: 'axios', nprogress: 'NProgress', 'vue-router': 'VueRouter', 'vue-quill-editor': 'VueQuillEditor' }) // 开发模式 config.when(process.env.NODE_ENV === 'development', config => { config.entry('app').clear().add('./src/main-dev.js') }) } } ``` 2. > 在public/index.html文件头部,将main-prod中的已经进行配置的import(样式表)删除替换为cdn引入 ```html ``` 3. > 在public/index.html文件头部,将main-prod中的已经进行配置的import(js文件)删除替换为cdn引入 ```html ``` 4. 使用cdn优化elementui打包 > 具体操作流程 > > 1. 在main-prod.js中,注释掉element-ui按需加载的代码 > > 2. 在index.html头部区域中,通过cdn加载element-ui的js和css样式 > > ``` > `` > > `` > > ``` > ``` 5. 优化前后对比 > 资源(2.9MB)=> 377.3kB > > 依赖项(1.4MB) => 122.2kB + Element-UI组件按需加载 + 路由懒加载 > 当打包构建项目时,JavaScript包会变得非常大。影响页面加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更高效。 [vue.config.js配置](https://cli.vuejs.org/zh/config/#lintonsave) [路由懒加载](https://router.vuejs.org/zh/guide/advanced/lazy-loading.html) [babel配置](https://babeljs.io/docs/en/babel-plugin-syntax-dynamic-import/) + 首页内容定制 > 不同的打包环境下,首页内容可能会有所不同。我们使用插件进行定制 + vue.config.js ```js config.plugin('html').tap(args => { args[0].isProd = true或false return args }) ``` + index.html ```html <%= htmlWebpackPlugin.options.isProd ? '' : 'dev-' %>vue-mall <% if(htmlWebpackPlugin.options.isProd) { %> css | js放在这儿 <% } %> ``` ### 项目上线 #### 通过node创建web服务器 > 新创建node项目,并安装express,通过express快速创建web服务器,将vue打包生成的dist文件夹,托管为静态资源即可,关键代码如下 ```js // 1. npm init -y // 2. npm i express -S // 3. 将打包后的dist放入node项目中 const express = require('express') const app = express() app.use(express.static('./dist')) app.listen(80, () => { console.log('server runing at http://127.0.0.1') }) // 5. node app.js启动项目 ``` #### 开启gzip配置 > 通过gzip减小文件体积,使传输速度更快 ##### 在服务器端使用express做gzip压缩,配置如下 ```js // 1.npm install compression -S // 2.导入包 const compression = require('compression') // 3.启用中间件 app.use(compression()) // 4.先进行静态资源的压缩,之后再挂静态资源 ``` #### 配置https服务 ##### 为什么要启用https服务 - 传统的http协议传输的数据都是明文,不安全 - 采用https协议对传输的数据进行了加密处理,可以防止数据被中间人窃取,使用更安全 申请ssl证书(https://freessl.org) => 正常企业还是使用收费ssh(http协议默认运行在80端口,https默认运行在443端口) #### 使用pm2管理应用 ```js 1. npm i pm2 -g //全局安装 2. pm2 start 脚本(如./app.js) --name 自定义名称 // 启动项目 3. pm2 ls //查看服务器运行的项目 4. pm2 restart 自定义名称 //重启项目 5. pm2 stop 自定义名称 //停止项目 6. pm2 delete 自定义名称 //删除项目 ``` ![image-20210817230741534](/images/image-20210817230741534.png) ### 错误异常 + vue中使用echarts报错:“TypeError: Cannot read property ‘init‘ of undefined”的解决方法 > 通过npm安装的是最新版echarts依赖,5.x版本,但是网上大部分教程的引入方式是按照4.x的方式引入,而5.x版本的引入方式有所改变,所以造成报错。 ```js //将引入方式换成最新的5.x的引入方式 import * as echarts from 'echarts' ``` + “Vue is not defined” 检查main.js文件和vue.config.js文件是否正确挂载 > 在HTML导入外部js时,有两种选择,一种是将js放在head体中,一种是将js放在body体中。如果将其放在head中,则js会在被调用时才执行。如果将其放在body中,则js会在页面加载时被执行。 + Vue报错“Cannot read property ‘0‘ of undefined”的解决办法 > 一般出问题都是出现的带有数组的变量中, 我们在使用之前需要先判断数组是否存在, 而且需要注意的是需要我们在数组变量所在的外层div中做一个判断该数组是否未定义 + 出现两个滚动条的解决方法 > 一般情况下当一个页面高度大于屏幕高度时(屏幕相当于父盒子)就会出现滚动轮。而当一个页面(这里是home页面)作为父盒子,它的子页面(cate页面)高度大于它(home页面)的高度,那么这个页面(home页面)就会出现滚动条。 ```css .com-page { padding: 20px; width: 100%; /* height: calc(100% - 56px); */ } ``` _让子页面的高度高于整个el-main的高度即可出现滚动条(由于com-page的高度不确定,故不可以确定为一个值,让其自动撑大即可)_ ![image-20210817230741534](/images/Snipaste_2021-08-18_14-02-29.png) ![image-20210817230741534](/images/Snipaste_2021-08-18_14-06-03.png) ![image-20210817230741534](/images/Snipaste_2021-08-18_14-06-46.png) + 使用Element-UI时无法对其样式进行覆盖 **使用全局样式表(!important)** ### 功能搭建 vue 实现点击按钮弹出div 点击页面其他位置,隐藏div **_vue click.stop阻止点击事件继续传播_** > + 给最外层的div加个点击事件 @click="screenRule=false" > + 给点击的元素上面加上:@click.stop="screenRule=!screenRule" 或者 @click.stop="screenRule=true" ### 项目总结 通过此次后端管理项目的搭建,熟悉vue+element-ui的快速项目搭建,熟练掌握vue-router机制,了解vue项目中的文件结构,学会对项目进行优化和上线,对项目的优化上线有了基本的认知。 ### 完成计划 做完本次项目之后对vue的掌握度更高,之后学习go之后会考虑用go撸一个后端代码(CRUD和权限控制)