前言
21年在校期间学习前端时,曾着手做过这个项目,但是因为后续的集训中途停止了,当时的博客笔记都存在了云里云外上。
现今随着学习的加深,当时很多不懂的地方,现在也有了大致的了解。
近期工作闲暇期间,希望能够重新写这个项目,完成当时未完成的任务,并且对现在的知识进行查漏补缺。
因此,将旧文从云里云外迁移至此,并做注释修改。后续重写项目,两边博客同步更新√。
一、vue项目:电商管理系统(开始)
时间:2021-6-29 11:33:31
本周开始着手做一个vue的项目,电商管理,通过b站的视频边学边做。
视频地址:BV1EE411B7SU
这个视频对新手超级友好,老师讲解的每一个点都很清晰。看的时候一定要打开弹幕!! 很多会遇到的问题,弹幕上都有解答,这帮了我不少忙,解决了很多小毛病。
前天将脚手架、git等需要的东西都下好了,唯独没有下载phpstudy和postman。因为一开始我以为这个视频是前后端都包含的,所以是不是有关后端的东西就不用安装呢(其实是因为我觉得他那个phpstudy不好,弹幕上还说有病毒)。
但是晚上做到登录跳转的时候,需要发送请求,发现没有api就是不行,这说明我对这些中间层的概念还是不够清晰,所有知识都只是浮于表面。
所以昨天就把那个postman也给安装上了,但是数据库我还是没有用phpstudy,而是用了Mysql+navicat导入了数据库文件,一样可以用,perfect~
视频中的项目使用了vue ui可视化面板,对新手比较友好,但是也有一定弊端。比如昨晚和振红学长讨论说用了这个,我们就不会通过命令创建项目啊,这是个问题。但是做事情讲究循序渐进,先从简单的做起大概了解一下整个的流程,然后再更深入的通过命令进行比对创建项目。
但是对于一个项目中的各种文件夹的作用,我们还是理解不够透彻,因此我上网去查了一下下。
菜鸟中有一个大概的解释,看着还蛮易懂的,Vue.js 目录结构
然后在csdn找到了一个更好懂的哈哈,适合小白:vue项目中的文件夹都是什么
这个里面写的就很清楚了,所以我也就不过多的阐述了,只写一些我觉得该写的😆
public:静态资源目录,相当于一个静态服务器。
public放不会改动的文件,这里面的内容可以是引用的,不是由自己编写的内容。
src:开发目录(关于这个目录下的各种也有一篇比较好懂的解释:vue 项目src文件夹结构和功能)
- assets:放置静态资源,包括公共的 css 文件、 js 文件、iconfont 字体文件、img 图片文件 以及其他资源类文件。之所以强调是公共的 css 文件,是因为要在组件的 css 标签里加入 ‘scoped‘ 标记,将其作用范围限制在此组件以及调用它的父级组件中,避免污染全局样式;
原文地址:https://www.yunliyunwai.cn/blog/detail/9fac2afb490b9f33497b5e75d612577f
二、vue项目:电商管理系统(登录部分)
时间:2021-6-29 16:45:14
登录部分
通过昨天一天,将整个登录请求,及后续退出和其他功能全部完善,然后着手做主页。
这个视频用到了一款饿了么开发的vue组件库,真的超级方便。让我不禁感叹技术的强大,但是存在一个问题,如果不用这个组件库或者用其他组件又该怎么编写呢,这个问题有待研究。
对于登录界面编写,老师讲解的都很清楚,但还是有点一知半解的感觉,可要我说哪里一知半解,我却又说不上来了。
所以就写一点,我明确不清楚的知识点。
- box-sizing:
- CSS box-sizing 属性(没太懂,他具体的作用是什么)
- box-sizing,这个更简单明了一点。
- CSS3 box-sizing 属性,这篇重点在于下面的两篇笔记。
- 就是说border-box就是在父元素定义好的长宽内,进行padding等边框的设计,不会导致溢出父元素。
- justify-content:
- justify-content,发现这个网站上的内容都挺易懂的,不错不错。
原文地址:https://www.yunliyunwai.cn/blog/detail/4c5c8bddc977bf2a13614309f125da42
三、vue项目:电商管理系统(主页-侧边栏部分)
时间:2021-6-29 17:01:47
主页-侧边栏部分
首先是对于element框架中menu部分的介绍:Menu
知识点:
-
unique-opened:是否只保持一个子菜单的展开
-
collapse:是否水平折叠收起菜单(仅在 mode 为 vertical 时可用)
-
collapse-transition:是否开启折叠动画
-
router:是否使用 vue-router 的模式,启用该模式会在激活导航时以 index 作为 path 进行路由跳转
-
1: el-menu 启用router,子菜单通过index直接跳转,获取path记得加/
-
2: path属性:返回指定文件、文件夹或驱动器的路径。
-
-
default-active:当前激活菜单的 index
-
1: 由于router属性的开启,子菜单的index值都是path跳转路径,所以需要先将index值保存在sessionStorage中,再通过属性绑定赋值给default-active
-
2: 为什么不能直接将index赋值给default-active呢?
-
1)首先,我觉得是因为default-active是menu的属性值,所以应该不能直接用subItem.path赋值。
-
2)其次,我尝试将saveNavState获取的值直接赋值给data中的activePath,发现这并不可行,刷新后高亮就失去了,还是需要再次点击。(不知道是不是我直接赋值的语句没搞对)
-
3)二级菜单是通过循环实现的,每个菜单的index值都不同,所以应该先暂存下来,再赋值给default-active
-
以上为本人个人言论,个人思想,均为“我觉得”,无任何根据,还有待考究,切勿引用。
-
-
3: 弹幕中有讲,可以直接用 default-active = $route.path
-
1)这个方法我试了一下,确实可行,刷新之后也同样会高亮。但是route代表的含义是?老师为什么没有用这个语句。
-
2)弹幕上说150+后就会出错,所以我打算看到150+后再回来看看会不会出错
-
-
4: 老师的这个方法有个小小小的bug(也可能是因为其他二级菜单没有弄好):
- 点了其他菜单之后再后退回来,其他菜单高亮。然而这时中间的主界面还是用户列表。
<!-- 侧边栏菜单区域 --> <el-menu background-color="#333744" text-color="#fff" active-text-color="#409eff" unique-opened :collapse="isCollapse":collapse-transition="false" router default-active="activePath"> <!-- 一级菜单 --> <el-submenu :index="item.id + ''" v-for="item in menulist" :key="item.id"> <!-- 一级菜单的模板区域 --> <template slot="title"> <!-- 图标 --> <i :class="iconsOBJ[item.id]"></i> <!-- 文本 --> <span>{{item.authName}}</span> </template> <!-- 二级菜单 --> <!-- router:是否使用 vue-router 的模式,启用该模式会在激活导航时以 index 作为 path 进行路由跳转 --> <!-- el-menu 启用router,子菜单通过index直接跳转,获取path记得加/ --> <!-- path属性:返回指定文件、文件夹或驱动器的路径。 --> <el-menu-item :index="'/' + subItem.path" v-for="subItem in item.children" :key="subItem.id" @click="saveNavState('/' + subItem.path)"> <template slot="title"> <!-- 图标 --> <i class="el-icon-menu"></i> <!-- 文本 --> <span>{{subItem.authName}}</span> </template> </el-menu-item> </el-submenu> </el-menu>
saveNavState(activePath){ window.sessionStorage.setItem('activePath',activePath); }
-
原文地址:https://www.yunliyunwai.cn/blog/detail/62986d8563e8982a4719822cd94a24c8
四、vue项目:电商管理系统(用户列表部分)
时间:2021-7-2 11:16:51
用户列表部分
编写用户列表部分的时候,不打算和之前一样边看边敲了,而是选择看一遍视频,然后凭借理解和记忆做出效果来。
前面的部分包括搜索、卡片、列表都很简单,就能写出来,但是做到状态的时候遇到了一个我不懂的知识点:插槽 (vue官方文档)
但是貌似这个知识点需要一个深入的了解,所以暂时先空下,先简单的了解他的意思。
用户列表做到修改用户状态时,项目报错了
This dependency was not found: * vue/types/umd in ./node_modules/cache-loade...
To install it, you can run: npm install --save vue/types/umd
Could not install from "vue\types\umd" as it does not contain a package.json file.
它说我缺少依赖包,叫我安装,可是我有啊。
我删了重安,安完重启,还是不行。百度搜了大半天,也不知道哪里错,说是导包有问题,可是Users.vue这个文件就没有导包。忙了一中午也没找出来,最后却发现,不知道什么时候多冒出来一句导包语句,可能是手误按到了😢
冒出这么一句没用到的导包语句,害我找了一中午错。
还好找到了,我可以继续战斗了!~
关于搜索部分,老师写的太简单,以至于我不知道原理是什么,为什么用了query就直接能查到数据了,他是怎么传递的。
以下为我的个人理解,不确定是否正确:
v-model进行数据双向绑定,query初值为空,input内输入字符串后,自动赋值给query,然后通过点击事件调用getUserList方法,通过get函数向服务器传递参数this.queryInfo,后端通过query关键字进行查询,然后返回信息通过res.data.user 赋值给userlist
添加用户部分
添加对话框的弹出和以往的界面弹出不同,这个项目中,将对话框写在卡片底部,然后设置隐藏,当点击添加按钮时取消隐藏,弹出对话框。
这是个页面本身就带有的对话框,只不过被隐藏掉了,而不是那种来自浏览器弹出的对话框。
添加表单的时候第一反应是table组件,但这是不对的,表单应该时form组件。table是表格,不包含数据的提交之类,只是显示数据,而form则通过提交进行后续操作。
做到邮箱、手机号合法性检验的时候,掌握了自定义检验的方法。但是美中不足的是,视频中的正则表达式看不懂😭,老师也没有讲解,只能自己去搜索去琢磨。
关于表单验证事件validate:对整个表单进行校验的方法,参数为一个回调函数。该回调函数会在校验结束后被调用,并传入两个参数:是否校验成功和未通过校验的字段。若不传入回调函数,则会返回一个 promise
对于箭头函数的理解,有篇博客看起来很好懂:vue中的箭头函数
添加用户过程中对于状态的判断总是记错,本应该是 if(res.meta.status !== 201)
我总写成 if(res !== 201)
。导致明明用户已经添加上了,可是却提示添加失败,界面也不刷新。
修改用户部分
修改用户和添加用户大同小异,很简单就能做好。我尽量都自己做一遍,做出来没问题后,再看视频看看老师是怎么写的。
在发送更新请求的部分,我通过
const { data: res } = await this.$http.put(’users/${this.editForm.id}‘, this.editForm)
方法发送请求,同样成功了,但是视频中老师并没有将一整个editForm对象都传过去,而是选择传递用到的参数。
const { data: res } = await this.$http.put('users/'+this.editForm.id, {email: this.editForm.email, mobile: this.editForm.mobile })
这里我不太理解为什么不能传整个参数,弹幕上说要按照API规则来,怎么写就怎么传。所以保险起见,我还是改回了老师用的代码。
删除用户部分
有了修改用户的基础,删除用户做的得心应手,仔细看了API文档,确定好路径、请求方式及参数,自己编写删除的请求。成功删除~
角色分配部分
关于这部分和权限列表相关联,所以等后面也都学完之后,粘个链接过来~
这一部分还学到不少东西,让后续的内容变得简单起来。
革命尚未成功,同志仍需努力!
加油吧!
原文地址:https://www.yunliyunwai.cn/blog/detail/296dbbb8aceaaa14cd43fb9dd4834327
五、vue项目:电商管理系统(权限列表部分)
时间:2021-7-4 11:30:22
权限列表部分
权限列表也可以自己动手做出来,就是在权限等级的位置不知道该怎么渲染,视频中用了v-if对获取到的数据进行了判定
角色列表按照之前的讲解,自己可以简单的渲染界面并获取数据,如下图
对于列表最前面的>不知道是用来干嘛的,所以不敢乱加,然后关于操作的按钮功能也先暂时不实现。
<!-- 添加角色按钮 -->
<el-button type="primary">添加角色</el-button>
视频中对于‘添加角色’按钮,先添加了一个行列的布局,再加入button。而我直接加了button,出来的效果是一样的,但是我不太理解二者的区别。可能是老师这么做更规范些,更不易出错?
<!-- 添加角色按钮区域 -->
<el-row>
<el-col>
<el-button type="primary">添加角色</el-button>
</el-col>
</el-row>
在对操作进行按钮渲染时,发现一个问题就是,列的强制宽度问题。一开始因为我的浏览器打开页面后,刚好三个按钮都在一排,所以我就没有设置强制宽度。但是,在做角色列表时突然意识到,一旦窗口缩小,三个按钮就不在同一行了,所以才要设置强制宽度,和一开始在不在一排没有关系。
对于表格前面的<,为展开列标志,因此,在表格渲染部分再加一列展开列。
对于操作栏内的按钮,需要自己来做,因为有之前的基础,所以很容易能做好。在提交编辑角色信息时使用了
const {data:res } = await this.$http.put('roles/' + this.editForm.id, { roleName: this.editForm.roleName, roleDesc: this.editForm.roleDesc})
结果返回一个错误,角色ID必须为数字,看了一遍检查代码觉得没有问题。打印一下this.editForm.id
未定义。
又仔细看了一下API文档,发现原来是id属性名打错了,应该是editForm.roleId
才对。
在展开列制作二级权限时,对于边框的处理不是很好。自己做的时候,按照一级权限的方式多设置了一个.bdno的样式取消掉了索引为0的二级权限边框,而视频中直接除了0以外都加上边框就好了。
<el-row :class="[i2 === 0 ? '':'bdtop']" v-for="(item2, i2) in item1.children" :key="item2.id">
在分配角色列表重置时,视频中将当前被分配角色的用户信息也一同重置了,我觉得即便不重置也可以,所以就只将selectRoleId重置了
原文地址:https://www.yunliyunwai.cn/blog/detail/1b6c484ba38fc0d4b22e4916cac2d813
结尾
以上为21年写该项目的旧文。