前些天读完几本书之后,现在准备整理一下去年工作的一些收获。
尤其是将其中一些自己没有参与,但是还比较关键的环节进行梳理。希望能有进一步的感想。
下面开始
登录退出功能
- 登录业务的相关技术点
- http是无状态的
- 通过cookie在客户端记录状态
- 通过session在服务端记录状态
- 通过token方式维持状态
如果前后端是存在跨域问题,那么推荐使用token方式。反之,就用cookie和session方式。
登录按钮所对应方法
1
2
3
4
5
6
7
8
9
10login() {
this.$refs.loginFormRef.validate(async validate => {
if (!validate) return
const { data: result } = this.$http.post('login', this.loginForm)
if (result.data.meta !== 200) return this.$message.error('登录失败')
this.$message.success('登录成功')
window.sessionStorage.setItem('token', result.data.token)
this.$router.push('/home')
})
}因为是仅网页打开期间需要,不用永久化存储,所以用sessionStorage。而不用localStorage
路由守卫控制访问权限
1
2
3
4
5
6
7
8
9
10// 为路由对象添加路由守卫
router.beforeEach(to, from, next) {
// 如果访问的是login页面,直接放行
if( to.path === '/login' ) return next()
// 从sessionStorage获取token
const tokenStr = window.sessionStorage.getItem('token')
// 如果没有token,强制跳转到login页面
if( !tokenStr ) return next('/login')
next()
}退出功能实现
1
2window.sessionStorage.clear()
this.$router.push('/login')
主页内容
- 发送请求的权限获取
因为是后台管理系统,所以除了login页面外,发送请求都需要Authorization
我们采取的是axios拦截器的方法
意思就是请求发起之前,在请求头中添加Authorization字段,并且将之设置为token1
2
3
4axios.interceptors.request.use(request => {
request.headers.Authorization = window.sessionStorage.getItem('token')
return request
})
权限管理
二级菜单点击可跳转,是因为el-menu设置了router
element-ui和vue中的插槽
个人理解的就是,如果某个元素内部还要依据自己的数据,进行下一步的处理。那么可以在内部使用插槽获取上级元素数据。比如dialog组件等
1
2
3<template slot-scope="scope">
{{scope.row}}
</template>表单预验证
1
2
3
4this.$refs.addFormRef.validate(valid => {
if (!valid) return
// 说明通过验证了,下一步发起请求
})权限管理部分-分配权限功能
首先是点击分配权限按钮,获取所有被选中的三级标签。采用递归的方法,具体实现如下1
2
3
4
5
6
7
8getLeafKeys(node, arr) {
if (!node.children) {
arr.push(node.id)
}
node.children.forEach(item => {
this.getLeafKeys(item, arr)
})
}
其次是提交时,获取所有选中和半选中的标签。调用element-ui提供的方法
1 | const key = [...this.$refs.treeRef.getCheckedKeys(),...this.$refs.treeRef.getHalfCheckedKeys()] |
商品管理
分类参数-标签管理
参数管理页面在添加tags时,当tags变成input之后,input自动获取焦点1
2
3
4
5
6
7
8showInput(row) {
row.inputVisible = true
// $nextTick当页面上元素被重新渲染之后,才会指定回调函数中的代码
// 👆注释的意思就是说等tags变成input之后再获取焦点,保证不出bug
this.$nextTick(_ => {
this.$refs.saveTagInput.$refs.input.focus()
})
}商品列表-添加时间
在main.js里面添加一个filter。主要解决的是时间格式的问题。具体来说是后台返回的是毫秒数,我们需要对应格式的时间。实现方式如下1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19Vue.filter('dateFormat',(originVal)=>{
const dt = new Date(originVal)
const y = dt.getFullYear()
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')
return `${y}-${m}-${d} ${hh}:${mm}:${ss}`
})
//String.prototype.padStart()
str.padStart(targetLength [, padString]) //语法
//例子如下
'abc'.padStart(10); // " abc"
'abc'.padStart(10, "foo"); // "foofoofabc"
'abc'.padStart(6,"123465"); // "123abc"
'abc'.padStart(8, "0"); // "00000abc"
'abc'.padStart(1); // "abc"
使用方法如下
1 | <el-table-column label="创建时间"> |
- 在数组中,找到指定index的元素,并返回index
1
2
3
4
5
6
7
8
9
10handleRemove(file) {
// console.log(file)
// 获取将要删除的图片的临时路径
const filePath = file.response.data.tmp_path
// 从pics数组中,找到这个图片对应的索引值
const i = this.addForm.pics.findIndex(x => x.pic === filePath)
// 调用splice方法,把图片移除
this.addForm.pics.splice(i, 1)
// console.log(this.addForm.pics)
}
项目优化上线
项目优化策略
1. 生成打包报告–命令行和图形界面
2. 第三方库开启 CDN
通过修改
vue.config.js
来修改webpack的配置
vue-cli3.0 默认隐藏了所有webpack的配置项,目的是为了屏蔽项目的配置过程,让具体功能和业务逻辑的实现称为中心为开发模式与发布模式指定不同的打包入口 通过externals加载外部CDN资源 首页内容定制
1 | // vue.config.js |
3. 通过CDN优化element-ui的打包
注释掉elemen-ui的引入,然后在index.html
头部引入element-ui的js和css文件
4. 路由懒加载
安装bebel/plugin-syntax-dynamic-import
在babel.config.js
中声明
1 | const Login = () => import(/* webpackChunkName: "index" */ '../components/Login.vue') |
5. 一些小点
添加NProcess
这个插件的作用就是在页面顶部添加一个加载的进度条。在请求开始时出现,得到相应后结束
具体实现如下1
2
3
4
5
6
7
8axios.interceptors.request.use( request => {
NProcess.start()
return request
})
axios.interceptors.response.use( response => {
NProcess.done()
return response
})build之后去除console
解决方法就是添加babel-plugin-transform-remove-console
项目上线
开启gzip配置,配置https服务,使用pm2管理应用
- 本文作者: Jambo
- 版权声明: 本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。转载请注明出处!