使用框架 | 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' //导入axios
axios.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"
border
row-key='cat_id'
:tree-props="{children: 'children',hasChildren: 'hasChildren'}"
> //table中使用:data来绑定数据
<el-table-column
label="序号"
width="60" type="index">
</el-table-column>
<el-table-column
prop="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) return
const {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