使用框架 element+vue
教程链接 https://www.bilibili.com/video/BV1bE411p7As?p=5

内容待整理,https服务还没有成功

项目初始化步骤

前端初始化

  1. 安装vue脚手架 (全局)npm i @vue/cli -g (安装一次即可)

可能出现的错误
permission denied:权限不够,需要在命令前面加上 sudo,代表以管理员的权限进行操作。

  1. 通过vue脚手架创建项目

如果要用终端创建项目,那么使用npm安装依赖
选择babel、router和使用配置文件

  1. 配置vue路由
  2. 配置element-ui组件库
  3. 配置axios库

    1. //main.js中配置
    2. import axios from 'axios' //导入axios
    3. axios.defaults.baseURL = '' //如果是api,那就把api提供到根路径放到这里
    4. Vue.prototype.$http = axios //挂载到vue原型上
  4. 初始化git远程仓库

  5. 将本地项目托管到github或码云中

后台项目的环境安装配置

  1. 安装mysql数据库
  2. 安装node.js环境

mysql

  1. 配置项目相关信息
    1. 拿到一个api文件-解压
    2. 在这个文件目录中运行终端 npm install
    3. node app.js(无报错为正常。我这里报错访问被拒绝,发现是mysql的密码和接口的密码对不上,所以修改了一下密码)
  2. 启动项目
  3. 使用postman测试后台项目接口是否正常

    查看项目相关信息

    终端中npm run serve
    然后打开提供的地址即可
    或者使用vue ui命令,打开后新建或者是导入自己的项目即可查看项目相关面板

    运行api接口

    将api文件夹在vscode中打开
    然后在终端中运行node app.js
    运行之前最好点击右下角go live 切换一个接口,避免端口占用

    端口冲突

    查看端口使用进程
    1. lsof -i:端口号
    释放进程
    1. kill 你的PID

登录与退出功能

保持登录

  • 通过cookie在客户端记录状态
  • 通过session在服务端记录状态
  • 通过token方式维持状态

不存在跨域问题,用前两个,存在跨域问题,则使用token

token原理

image.png

用户列表功能

如何获取行数据(使用插槽v-slot)

在需要用到行数据的标签外部,加入一个<template v-slot='slotProps'>``</template>通过v-slot绑定行数据,这样就可以通过slotProps.row.具体数据拿到需要的数据。

路由跳转

全局配置

  1. //路由文件中的配置
  2. import Vue from 'vue'
  3. import VueRouter from 'vue-router'
  4. import login from '../components/login.vue'
  5. import home from '../components/home.vue'
  6. import welcome from '../components/welcome.vue'
  7. import users from '../components/user/users.vue'
  8. import rights from '../components/power/rights.vue'
  9. import roles from '../components/power/roles.vue'
  10. import goods from '../components/goods/goods.vue'
  11. import cate from '../components/goods/cate.vue'
  12. import params from '../components/goods/params.vue'
  13. //先导入组件
  14. //然后定义路径
  15. const router = new VueRouter({
  16. routes:[
  17. {path:'/',redirect:'/login'},
  18. {path:'/login',component:login},
  19. {path:'/home',component:home,
  20. redirect:'/welcome',
  21. children:[
  22. {path:'/welcome',component:welcome},
  23. {path:'/users',component:users},
  24. {path:'/rights',component:rights},
  25. {path:'/roles',component:roles},
  26. {path:'/goods',component:goods},
  27. {path:'/categories',component:cate},
  28. {path:'/params',component:params},
  29. // 一般子路由的前面不需要加斜杠,但是这个是在页面内部重定向加组件,需要加斜杠
  30. ]}
  31. ]
  32. })
  33. //这些定义完成后,把需要放这些组件的模块中,加入一个<router-view></router-view>即可

组件内配置

  1. //如果在组件内进行跳转,则可以使用
  2. this.$router.push('/goods/add')
  3. //然后在路由文件中像上面一样定义一下即可

新增和删除使用同一个弹窗

判断是否有id即可,如果id为undefined,说明没有id执行新增函数,如果有则执行编辑函数。
要注意用的是哪个id,如果是判断是否有角色roleId,那么和用户列表获取到的id是不一样。
还有一个点是,不能在addForm(也就是你要提交的列表数据)里面定义roleId,哪怕是一个空值也不行,因为空值不是undefined,空值也是有值的。所以它永远不会走新增的逻辑。

resetFields() undefined

第二个方法

解构赋值

  1. const {data:res} = await this.$http.get(`categories/${this.cateId}/attributes`,{params:{sel:'many'}})
  2. //前面 {data:res}的部分就是解构赋值,意思是,右边的请求返回的数据data,通过 {data:res}的形式,将data重命名为res

加间隔

<div style="margin: 20px;"></div>

async await

  1. async get(){
  2. const {data:res} = await this.$http.get(`categories/${this.cateId}/attributes`,{params:{sel:'many'}})
  3. }

在函数名称前面加上async,请求前面加上await可以实现异步操作。

.then .catch

正则表达式

角色列表功能

循环递归

循环递归三级列表的id,以此获得选中状态。

  1. getLeafKeys(node,arr){
  2. //调用的时候,这里的node和arr要放上自己要处理的数组(node)和处理完成之后获得的id数组(arr)
  3. if(!node.children){
  4. return arr.push(node.id)
  5. }
  6. node.children.forEach(item =>
  7. this.getLeafKeys(item,arr)
  8. );

如果要给标签加上一个为布尔值的属性,则需要绑定,前面加上:,不然会识别成字符串

如何获取ID

表格行中,可以通过v-slot传过来,但是如果是弹窗中的确定按钮,则可以在展开弹窗的时候,把获取到的角色id保存到数据中。

展开运算符

展开运算符,将一个数组转为用逗号分隔的参数序列。

  1. [...this.$refs.定义的ref名称.函数]

发送请求体

请求体是一个对象{名称(也就是接口要求传的参数名称):值(具体的值从哪里获取)}
示例

  1. {sel:'many'}
  2. {sel:this.addForm}

分类参数功能

计算属性

  1. computed:{
  2. disabled(){
  3. if(this.selectedkeys.length!==3){
  4. return true
  5. }
  6. return false
  7. },
  8. }
  9. //disabled可以被绑定给一个属性。
  10. //计算属性里面的函数也可以通过this获取到

表单绑定

  1. <el-form ref="addFormRef" :model="attr" label-width="80px" :rules="attrule">
  2. //表单中使用:model来绑定数据
  3. <el-form-item :label="titleText" prop='attr_name'> //表单中的prop是用来绑定校验规则的
  4. <el-input v-model="attr.attr_name" ></el-input> //v-model来确定每一项具体绑定对象中的哪一个属性。
  5. </el-form-item>
  6. </el-form>

表格绑定

  1. <el-table
  2. :data="cateLists"
  3. border
  4. row-key='cat_id'
  5. :tree-props="{children: 'children',hasChildren: 'hasChildren'}"
  6. > //table中使用:data来绑定数据
  7. <el-table-column
  8. label="序号"
  9. width="60" type="index">
  10. </el-table-column>
  11. <el-table-column
  12. prop="cat_name"
  13. label="分类名称"
  14. width="180"> //表格中使用prop来确定每一项具体绑定哪一个属性
  15. </el-table-column>
  16. </el-table>

商品列表功能

校验规则

单条校验

prop的值和rules校验规则中的值要与input绑定的值(v-model)一样,否则就会报错

  1. <el-form ref="addFormRef" :model="addForm" label-width="80px" class="addform" :rules="addFormRules">
  2. <el-form-item label="商品名称" prop="goods_name">
  3. <el-input v-model="addForm.goods_name"></el-input>
  4. </el-form-item>
  5. <el-form-item label="商品价格" prop="goods_price" >
  6. <el-input-number v-model="addForm.goods_price" controls-position="right" @change="handleChange" style="width:100%" :min='0'></el-input-number>
  7. </el-form-item>
  8. <el-form-item label="商品重量" prop="goods_weight" >
  9. <el-input-number v-model="addForm.goods_weight" controls-position="right" @change="handleChange" style="width:100%" :min='0'></el-input-number>
  10. </el-form-item>
  11. <el-form-item label="商品数量" prop="goods_number" >
  12. <el-input-number v-model="addForm.goods_number" controls-position="right" @change="handleChange" style="width:100%" :min='0'></el-input-number>
  13. </el-form-item>
  14. </el-form>
  15. <script>
  16. data(){
  17. return{
  18. addFormRules:{
  19. goods_name:[
  20. {required:true,
  21. message:'请输入商品名称',
  22. trigger:'blur',
  23. }
  24. ],
  25. goods_price:[
  26. {required:true,
  27. message:'请输入商品价格',
  28. trigger:'blur',
  29. }
  30. ],
  31. goods_weight:[
  32. {required:true,
  33. message:'请输入商品重量',
  34. trigger:'blur',
  35. }
  36. ],
  37. goods_number:[
  38. {required:true,
  39. message:'请输入商品数量',
  40. trigger:'blur',
  41. }
  42. ]
  43. }
  44. }
  45. }
  46. </script>

表单整体校验

  1. this.$refs.addFormRef.validate(async valid=>{
  2. if(!valid) return
  3. const {data:res} = await this.$http.post('users',this.addForm)
  4. if(res.meta.status!==201)return this.$message.error('添加用户失败'), console.log(this.addForm);
  5. this.$message.success('添加用户成功')
  6. this.adddialogFormVisible = false;
  7. this.getUserList()
  8. })

vue@click绑定多个事件

一定要带上括号

  1. <div @click="show();scrollLyric()" class="showImg">

深拷贝

把对象原封不动拷贝一份,与元数据互不相干
安装lodash

组件页面之间的传值

keep-alive

实现缓存

数据统计功能

使用echarts

//1.npm安装echarts
npm install echarts --save

//2.script中导入echarts
import * as echarts from 'echarts'

//3.template中定义放图表的地方
 <div id="main" style="width: 600px;height:400px;"></div>

//4.mounted中进行配置
  // 基于准备好的dom,初始化echarts实例
 var myChart = echarts.init(document.getElementById('main'));
                    // 指定图表的配置项和数据
          var option = {
            title: {
                text: 'ECharts 入门示例'
            },
            tooltip: {},
            legend: {
                data:['销量']
            },
            xAxis: {
                data: ["衬衫","羊毛衫","雪纺衫","裤子","高跟鞋","袜子"]
            },
            yAxis: {},
            series: [{
                name: '销量',
                type: 'bar',
                data: [5, 20, 36, 10, 10, 20]
            }]
        };

        // 使用刚指定的配置项和数据显示图表。
        myChart.setOption(option);

项目优化

  1. 生成打包报告
  2. 第三方启用CDN
  3. Element-UI组件按需加载
  4. 路由懒加载
  5. 首页内容定制

通过nprogress添加进度条效果

//在main.js中定义
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'

//在axios配置中加入进度条的函数。进度条于发起请求有关,与路由无关
Vue.prototype.$http = axios
axios.defaults.baseURL='http://127.0.0.1:3030/api/private/v1/'
// 在request拦截器中,显示进度条nprogress.start()
axios.interceptors.request.use(config=>{
  NProgress.start()
  config.headers.Authorization=sessionStorage.getItem('token')
  return config
})
// 在response拦截器中,隐藏进度条nprogress.done()
axios.interceptors.response.use(config=>{
  NProgress.done()
  return config
})

只在发布阶段移除所有的console

使用这个babel-plugin插件

npm进行安装
npm install babel-plugin-transform-remove-console --save-dev

安装后文件列表中会出现babel.config.js的文件

//在plugin中配置"transform-remove-console"

const prodPlugins = []
if(process.env.NODE_ENV==='production'){
  prodPlugins.push('transform-remove-console')
}

module.exports = {
  "presets": [
    "@vue/cli-plugin-babel/preset"
  ],
  "plugins": [
    [
      "component",
      {
        "libraryName": "element-ui",
        "styleLibraryName": "theme-chalk"
      }
    ],
    ...prodPlugins  //...代表展开运算符,展开的内容是在别处定义的,在这里使用...将代码展开
  ]
}

生成打包报告

使用命令行

npm run build --report //使用命令行

使用可视化面板

查看体积较大的文件是哪些,后续优化体积比较大的文件

vue ui //查看 build 中控制台和分析页面

修改webpack默认配置

通过vue-cli 3.0工具生成的项目,默认隐藏了所有webpack的配置项
如果有修改webpack默认配置的需求,可以按需创建vue.config.js这个文件,具体如何配置参考vue.config.js

configureWebpack

通过操作对象的形式,来修改默认的webpack配置

chainWebpack

通过链式编程的形式,来修改默认的webpack配置
自定义打包入口

 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')
        })
    }

通过externals加载外部CDN资源

优化包的大小

  1. 在main-prod.js中注释掉引入的css和js文件,取代以public中index.html中的CDN链接

自定制首页内容

开发模式在标题前加dev-

//public中index.html中 title的配置
<title><%= htmlWebpackPlugin.options.isProd ? '':'dev - ' %>电商后台管理系统</title>

//vue.config.js中
//发布模式中
config.plugin('html').tap(args=>{
                args[0].isProd = true
                return args

//开发模式中
  config.plugin('html').tap(args=>{
                args[0].isProd = false
                return args

//public中index.html中把所有以CDN样式链接的样式表和js用下面两个标签括起来
     <% if(htmlWebpackPlugin.options.isProd){ %>
       <% } %>

路由懒加载

  1. 安装@babel/plugin-synamic-import包👉🏻安装
  2. 在babel.config.js配置文件中声明该插件

    //plugins中声明
    '@babel/plugin-syntax-dynamic-import'
    
  3. 将路由改为按需加载的形式,示例代码如下

    const Foo = () => import(/* webpackChunkName: "group-foo" */ './Foo.vue')
    const Bar = () => import(/* webpackChunkName: "group-foo" */ './Bar.vue')
    const Baz = () => import(/* webpackChunkName: "group-foo" */ './Baz.vue')
    //webpackChunkName是分组的意思,名称相同的会被打包到一个js中
    

项目上线

  1. 通过node创建web服务器
  2. 开启gzip配置
  3. 配置https服务
  4. 使用pm2管理应用

通过node创建web服务器

项目文件夹同级目录下新建’shop_server’(这个就是你的服务端)

  1. 将文件夹在vscode中打开,打开终端,输入npm init -y ,初始化包管理。
  2. npm i express -S
  3. 将shop(你的项目)中的dist文件夹复制到 shop_server
  4. 在shop_server中新建app.js文件,配置如下代码 ```javascript const express = require(‘express’) const app = express() // 托管的静态资源的目录 app.use(express.static(‘./dist’))

app.listen(80,()=>{ console.log(‘server running at http://127.0.0.1‘); })


<a name="areFI"></a>
### 开启gzip配置
gzip可以减小文件体积,加快加载速度<br />可以通过服务端使用express进行gzip压缩(打开shop_server,进入终端),配置如下
```javascript
//安装
npm i compression -S
//app.js中导入
const compression = require('compression')

配置https服务

前端可以略作了解,一般是后端的工作

  1. freessl.cn中免费注册一个(仅作学习用),推荐选择通配符域名👉🏻点击创建
  2. 输入邮箱,下面的内容保持默认即可👉🏻确定

需要安装一个keymanager

使用pm2管理应用

  1. 在服务端安装pm2:npm i pm2 -g
  2. 启动项目:pm2 start 脚本 —name(自定义名称)
  3. 查看运行项目:pm2 ls
  4. 重启项目:pm2 restart 自定义名称/id(ls可以查看id)
  5. 停止项目:pm2 stop 自定义名称/id
  6. 删除项目:pm2 delete 自定义名称/id