| 使用框架 | element+vue |
|---|---|
| 教程链接 | https://www.bilibili.com/video/BV1bE411p7As?p=5 |
内容待整理,https服务还没有成功
项目初始化步骤
前端初始化
- 安装vue脚手架 (全局)npm i @vue/cli -g (安装一次即可)
可能出现的错误
permission denied:权限不够,需要在命令前面加上 sudo,代表以管理员的权限进行操作。
- 通过vue脚手架创建项目
如果要用终端创建项目,那么使用npm安装依赖
选择babel、router和使用配置文件
- 配置vue路由
- 配置element-ui组件库
配置axios库
//main.js中配置import axios from 'axios' //导入axiosaxios.defaults.baseURL = '' //如果是api,那就把api提供到根路径放到这里Vue.prototype.$http = axios //挂载到vue原型上
初始化git远程仓库
- 将本地项目托管到github或码云中
后台项目的环境安装配置
- 安装mysql数据库
- 安装node.js环境
- 配置项目相关信息
- 拿到一个api文件-解压
- 在这个文件目录中运行终端 npm install
- node app.js(无报错为正常。我这里报错访问被拒绝,发现是mysql的密码和接口的密码对不上,所以修改了一下密码)
- 启动项目
- 使用postman测试后台项目接口是否正常
查看项目相关信息
终端中npm run serve
然后打开提供的地址即可
或者使用vue ui命令,打开后新建或者是导入自己的项目即可查看项目相关面板运行api接口
将api文件夹在vscode中打开
然后在终端中运行node app.js
运行之前最好点击右下角go live 切换一个接口,避免端口占用端口冲突
查看端口使用进程
释放进程lsof -i:端口号
kill 你的PID
登录与退出功能
保持登录
- 通过cookie在客户端记录状态
- 通过session在服务端记录状态
- 通过token方式维持状态
token原理
用户列表功能
如何获取行数据(使用插槽v-slot)
在需要用到行数据的标签外部,加入一个<template v-slot='slotProps'>``</template>通过v-slot绑定行数据,这样就可以通过slotProps.row.具体数据拿到需要的数据。
路由跳转
全局配置
//路由文件中的配置import Vue from 'vue'import VueRouter from 'vue-router'import login from '../components/login.vue'import home from '../components/home.vue'import welcome from '../components/welcome.vue'import users from '../components/user/users.vue'import rights from '../components/power/rights.vue'import roles from '../components/power/roles.vue'import goods from '../components/goods/goods.vue'import cate from '../components/goods/cate.vue'import params from '../components/goods/params.vue'//先导入组件//然后定义路径const router = new VueRouter({routes:[{path:'/',redirect:'/login'},{path:'/login',component:login},{path:'/home',component:home,redirect:'/welcome',children:[{path:'/welcome',component:welcome},{path:'/users',component:users},{path:'/rights',component:rights},{path:'/roles',component:roles},{path:'/goods',component:goods},{path:'/categories',component:cate},{path:'/params',component:params},// 一般子路由的前面不需要加斜杠,但是这个是在页面内部重定向加组件,需要加斜杠]}]})//这些定义完成后,把需要放这些组件的模块中,加入一个<router-view></router-view>即可
组件内配置
//如果在组件内进行跳转,则可以使用this.$router.push('/goods/add')//然后在路由文件中像上面一样定义一下即可
新增和删除使用同一个弹窗
判断是否有id即可,如果id为undefined,说明没有id执行新增函数,如果有则执行编辑函数。
要注意用的是哪个id,如果是判断是否有角色roleId,那么和用户列表获取到的id是不一样。
还有一个点是,不能在addForm(也就是你要提交的列表数据)里面定义roleId,哪怕是一个空值也不行,因为空值不是undefined,空值也是有值的。所以它永远不会走新增的逻辑。
resetFields() undefined
解构赋值
const {data:res} = await this.$http.get(`categories/${this.cateId}/attributes`,{params:{sel:'many'}})//前面 {data:res}的部分就是解构赋值,意思是,右边的请求返回的数据data,通过 {data:res}的形式,将data重命名为res
加间隔
<div style="margin: 20px;"></div>
async await
async get(){const {data:res} = await this.$http.get(`categories/${this.cateId}/attributes`,{params:{sel:'many'}})}
在函数名称前面加上async,请求前面加上await可以实现异步操作。
.then .catch
正则表达式
角色列表功能
循环递归
循环递归三级列表的id,以此获得选中状态。
getLeafKeys(node,arr){//调用的时候,这里的node和arr要放上自己要处理的数组(node)和处理完成之后获得的id数组(arr)if(!node.children){return arr.push(node.id)}node.children.forEach(item =>this.getLeafKeys(item,arr));
如果要给标签加上一个为布尔值的属性,则需要绑定,前面加上:,不然会识别成字符串
如何获取ID
表格行中,可以通过v-slot传过来,但是如果是弹窗中的确定按钮,则可以在展开弹窗的时候,把获取到的角色id保存到数据中。
展开运算符
展开运算符,将一个数组转为用逗号分隔的参数序列。
[...this.$refs.定义的ref名称.函数]
发送请求体
请求体是一个对象{名称(也就是接口要求传的参数名称):值(具体的值从哪里获取)}
示例
{sel:'many'}{sel:this.addForm}
分类参数功能
计算属性
computed:{disabled(){if(this.selectedkeys.length!==3){return true}return false},}//disabled可以被绑定给一个属性。//计算属性里面的函数也可以通过this获取到
表单绑定
<el-form ref="addFormRef" :model="attr" label-width="80px" :rules="attrule">//表单中使用:model来绑定数据<el-form-item :label="titleText" prop='attr_name'> //表单中的prop是用来绑定校验规则的<el-input v-model="attr.attr_name" ></el-input> //v-model来确定每一项具体绑定对象中的哪一个属性。</el-form-item></el-form>
表格绑定
<el-table:data="cateLists"borderrow-key='cat_id':tree-props="{children: 'children',hasChildren: 'hasChildren'}"> //table中使用:data来绑定数据<el-table-columnlabel="序号"width="60" type="index"></el-table-column><el-table-columnprop="cat_name"label="分类名称"width="180"> //表格中使用prop来确定每一项具体绑定哪一个属性</el-table-column></el-table>
商品列表功能
校验规则
单条校验
prop的值和rules校验规则中的值要与input绑定的值(v-model)一样,否则就会报错
<el-form ref="addFormRef" :model="addForm" label-width="80px" class="addform" :rules="addFormRules"><el-form-item label="商品名称" prop="goods_name"><el-input v-model="addForm.goods_name"></el-input></el-form-item><el-form-item label="商品价格" prop="goods_price" ><el-input-number v-model="addForm.goods_price" controls-position="right" @change="handleChange" style="width:100%" :min='0'></el-input-number></el-form-item><el-form-item label="商品重量" prop="goods_weight" ><el-input-number v-model="addForm.goods_weight" controls-position="right" @change="handleChange" style="width:100%" :min='0'></el-input-number></el-form-item><el-form-item label="商品数量" prop="goods_number" ><el-input-number v-model="addForm.goods_number" controls-position="right" @change="handleChange" style="width:100%" :min='0'></el-input-number></el-form-item></el-form><script>data(){return{addFormRules:{goods_name:[{required:true,message:'请输入商品名称',trigger:'blur',}],goods_price:[{required:true,message:'请输入商品价格',trigger:'blur',}],goods_weight:[{required:true,message:'请输入商品重量',trigger:'blur',}],goods_number:[{required:true,message:'请输入商品数量',trigger:'blur',}]}}}</script>
表单整体校验
this.$refs.addFormRef.validate(async valid=>{if(!valid) returnconst {data:res} = await this.$http.post('users',this.addForm)if(res.meta.status!==201)return this.$message.error('添加用户失败'), console.log(this.addForm);this.$message.success('添加用户成功')this.adddialogFormVisible = false;this.getUserList()})
vue@click绑定多个事件
一定要带上括号
<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);
项目优化
- 生成打包报告
- 第三方启用CDN
- Element-UI组件按需加载
- 路由懒加载
- 首页内容定制
通过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
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资源
优化包的大小
- 在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){ %>
<% } %>
路由懒加载
- 安装@babel/plugin-synamic-import包👉🏻安装
在babel.config.js配置文件中声明该插件
//plugins中声明 '@babel/plugin-syntax-dynamic-import'将路由改为按需加载的形式,示例代码如下
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中
项目上线
- 通过node创建web服务器
- 开启gzip配置
- 配置https服务
- 使用pm2管理应用
通过node创建web服务器
项目文件夹同级目录下新建’shop_server’(这个就是你的服务端)
- 将文件夹在vscode中打开,打开终端,输入
npm init -y,初始化包管理。 - npm i express -S
- 将shop(你的项目)中的dist文件夹复制到 shop_server
- 在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服务
前端可以略作了解,一般是后端的工作
- freessl.cn中免费注册一个(仅作学习用),推荐选择通配符域名👉🏻点击创建
- 输入邮箱,下面的内容保持默认即可👉🏻确定
需要安装一个keymanager
使用pm2管理应用
- 在服务端安装pm2:npm i pm2 -g
- 启动项目:pm2 start 脚本 —name(自定义名称)
- 查看运行项目:pm2 ls
- 重启项目:pm2 restart 自定义名称/id(ls可以查看id)
- 停止项目:pm2 stop 自定义名称/id
- 删除项目:pm2 delete 自定义名称/id
