前端技术栈
vue、vue-router(路由)、Element-UI、Axios(发起网络数据请求)、Echarts(绘制图形报表)
后端技术栈
node.js、MySQL、Jwt(状态保持功能,等于session那样的)
项目初始化
安装vue脚手架
vue ui可视化创建项目并进行配置
配置vue路由
配置element-ui
配置axios库
将本地项目托管到github中
本地项目上传Github
1.在文件夹中右键“Git Bash Here”,并在命令行中输入git init把这个文件夹变成git可管理的仓库
2.通过“git add .”把文件添加到缓存区、然后使用命令“git commit -m 注释”把文件提交到本地仓库
3.将Git仓库和本地仓库进行关联,输入“git remote add origin git@github.com:smfx1314/test2.git”
4.把本地库中的所有内容推送到远程仓库,通过“git push -u origin master”,由于新建的远程仓库是空的,所以要加上-u这个参数。等远程仓库里面有了内容之后,下次再从本地库上传内容的时候只需下面这样就可以了:“git push origin master”。
配置API接口服务器并使用postman调试接口
进入文件中安装依赖包,安装完成后直接运行node .\app.js就可以跑项目,验证接口需要使用postman。
登录业务
流程:在登录界面输入用户名和密码、调用后台接口进行验证、通过验证后根据后台的响应状态跳转到项目主页
技术点:cookie在客户端记录状态,通过session在服务器端记录状态(不存在跨域),通过token方式维持状态(项目存在跨域问题的时候使用这个方法,跨域就是前后端端口号不一致,不能相互访问数据)
实现Login组件并完成重定向
等访问根页面时,重定向到/login页面
登录模块的html和css实现
其中涉及到模块居中以及表单格式的css知识
通常居中会用到:position: absolute; left: 50%;top: 50%; transform: translate(-50%, -50%);
而表单的格式:position: absolute;bottom: 0;width: 100%;padding: 0 20px;box-sizing: border-box;
表单的数据绑定
首先为el-form中加入“:model=form”完成数据绑定,指向一个数据对象,然后为每一个表单项通过v-model=form.name绑定到数据对象上对应的属性中。
表单的数据验证
可以先查看element-ui中表单验证这块的组件,具体步骤,对el-form通过属性绑定制定一个:rules="rules"校验,在data中定义rules校验对象,每个属性都是一个验证规则,为每个表单对象el-form-item通过prop制定对应的验证规则。
表单的重置
通过element-ui中的resetFields函数对表单中的实例对象进行重置,首先要获得表单中的实例对象,可以在el-form通过ref="ref",对重置按钮设置一个@click点击触发的函数,在methods中定义这个函数,并引用resetFields()函数
登录前表单数据的预验证
通过调用validate函数可以对表单进行校验,具体方法和重置差不多
配置axios发起登录请求
打开数据库,再通过powershell运行app.js文件
message弹框显示登录情况
登录后的操作
将登录后的token保存到客户端的sessionStorage中,这是因为项目的其他api接口,必须在登录成功后才能访问。
sessionStorage是会话期间的存储机制,localStorage是持久化的存储机制,token是在当前网站打开期间生效,所以把token保存到sessionStorage比较合适。
通过编程式导航跳转到后台主页。this.$router.push('/home')
通过路由导航守卫控制访问权限
如果用户没有登录,但是直接通过url访问了特定页面,需要导航到登录页面。router.beforeEach函数
退出功能
基于token退出只需要消除本地的token
主页布局
fs capture来获取颜色,使用element-ui中的容器组件对主页进行布局
header区域的布局
element-ui提供的navmenu导航菜单
通过接口来获取菜单数据
需要授权的 API ,必须在请求头中使用 `Authorization` 字段提供 `token` 令牌
通过axios请求拦截器添加token,保证拥有获取数据的权限
获取到数据后渲染
通过两层v-for循环渲染列表,并对菜单进行优化,比如每次只能打开一个菜单,还有折叠与展开功能
侧边栏路由链接
修改menu中的router参数:是否使用 vue-router 的模式,启用该模式会在激活导航时以 index 作为 path 进行路由跳转
绘制用户列表中的的组件
栅格布局
通过插槽渲染状态
状态列中:只要通过v-slot定义作用域插槽,接收 scope,就可以得到scope.row,即这行的数据,即可相应的改变开关的状态
修改用户状态
首先需要一个监听@change事件,当修改状态时需要通过axios请求将状态同步到服务器中
完成搜索功能
完成数据的双向绑定,然后再加一个点击事件是完事了。然后clearable清空文本框,出发一个clear事件就又可以看到搜索前全部的内容了
添加用户对话框的展示
对话框内容的验证,可以自定义一个验证规则,在data里面定义一个变量,他的值指向一个箭头函数,箭头函数的形参中包含了三个变量。在用这个规则的时需要在rules里面通过validator指定具体的校验规则
表单数据的重置
对对话框监听一个关闭事件,但对话框关闭时,触发事件,通过ref,对数据进行重置,resetFields()
关于表单的预校验
顾名思义,先将用户在表单中的数据进行整体的预校验,如果校验成功的话,再根据接口的信息发起添加用户的网络请求。这里的预校验遇到了一些问题,validate函数返回的一直返回undefined,检查了半天才发现原来之前的自定义校验里的返回函数没有严格按照element-ui文档中的进行编写,难顶啊!
修改用户信息
添加一个修改用户信息对话框,在对话框设置:visible.sync="editDialogVisible",然后通过点击修改,触发一个展示对话框的函数,函数中将editDialogVisible 设置为true即可展示
根据id搜索对应的用户信息
通过v-slot定义作用域插槽,接收 scope,就可以得到scope.row.id,即这行的数据中的id数值,再根据id数值对服务器发起get请求得到用户的信息以供修改对话框展示
修改表单的验证规则
同添加用户表单,做一些简单的修改即可
完成修改表单前的预验证
预验证后,发起修改用户的put请求
删除用户
弹框询问是否确认删除,$confirm需要先进行挂载才能使用,因为this是当前组件的实例,然后通过.then指定成功之后的操作,.catch用户取消之后的操作。
权限管理功能模块
准备工作:在GitHub中创建一个rights分支,接下来对于权限的开发就在这个分支上进行
完成权限列表页面的基本内容,如面包屑导航和卡片视图,并通过路由的形式展现出来
然后通过调用接口get方法获取到权限列表
渲染权限列表的UI结构
同理导入角色列表
角色列表添加展开列
通过设置el-table-column中的type="expand",即可添加展开列
展开列中的内容,通过作用域插槽的方法得到是最方便的!
之后需要渲染展开列中的内容,需要用到for循环,一层一层地渲染权限内容,这里面涉及el-row el-col :span的内容,需要及时消化!
再对列表进行美化,主要是对内容进行竖直方向上的居中,通过display: flex; align-items: center;实现,在需要的标签中进行类定义即可。
权限的删除
删除完成后,不建议调用methods方法中的getRolesList()函数,那样展开列会关闭,我们直接将结果中的data赋值给role.children,即可不用关闭展开列,并完成删除操作,能防止列表的刷新,给用户一个更好的体验。
分配权限
准备:分配权限对话框的弹出,要获取所有权限的数据,以一个树型结构加载出来,所有在接口请求的时候,type的类型要选择tree。获取到数据后,我们用element-ui中的树形控件表示出来,并添加复选框。复选框可以通过设置:default-checked-keys="defKeys",这里用到了一个递归函数来获取三级权限的id值并保存到defKeys中,来展示默认勾选的节点。
分配权限功能bug
当我们点击分配权限时,把当前id下的权限全都送到了defKeys中去了,但是关闭对话框后并没有清空defKeys中的内容,这样会导致点击权限越多,显示的权限会越来越多,只需要监听对话框关闭事件触发一个清空的函数即可。
分配权限功能实现
实现了具体的权限分配功能,在点击分配权限按钮后,我们立即将当前角色的id保存到data()中供后续使用,然后点击确定按钮后,获取了整个树形结构中那些半选和全选状态的id值然后把他们送到一个数组中,接着根据接口文档需要,我们把得到的数组用“,”做了一次拼接,发起post请求发送到服务器端。然后刷新我们的列表。
分配角色事件
之前的分配角色还没有完成,我们在学习了分配权限后,利用已有的知识去完成分配角色部分!这里在操作上与分配权限不同的就是通过获取所有角色列表,用一个下拉对话框进行选择,道理是同分配权限一样的。
这里还是有一个问题,当修改完一个用户的角色后,再想修改时,对话框的中的内容仍然是原先角色的信息,故需要监听对话框的关闭事件,当关闭一个对话框时,要把id值和用户信息都置为空。
商品分类
首先还是像用户和权限一样,先写好页面的基本布局,然后向服务器请求数据,但是这里请求数据格式与之前不同,如果还是像之前一样将res.data赋值给catelist的话,不行,通过console.log将结果打印出来后发现我们需要的数据在res.data.result中。
商品表格
一个添加了一个依赖——vue-table-with-tree-grid,然后将这个包导入到项目中去制作商品的表格。
模板列,需要在columns中定义type为template去指定具体的作用域插槽,其他的操作和平时的作用域插槽没多大区别。
分页功能还是使用element-ui中的分页组件,并定义其中的事件
商品分类中添加分类
添加分类对话框中,父级分类要用到一个级联选择器
先调用服务器请求获取父级列表的数据,:options绑定商品列表,props则绑定用户选择的选项的id,name和children,@change="parentCateChanged"是用户在选项发生变化时将addForm中的数据进行设置。
分类参数
首先还是渲染页面,完成面包屑导航、级联选择器,因为设置参数只允许设置三级分类商品的参数,于是需要在handleChanged()函数中添加一个判断,如果不是三级分类的话,则需要将一些值置为0。
然后就是从服务器中获取3级分类的参数列表并渲染到页面,这里会遇到一个问题,当我们点击3级分类后,服务器会把动态属性的参数列表打印出来,但是我们转到静态属性时,却不打印参数了。这里需要将请求参数的函数另外声明,当我们在切换时,再调用这个函数即可打印出各自的参数。
完成了添加参数、属性的功能,以及删除参数的功能。
分类中的展开行的内容,用split函数将字符串分割为数组,再用v-for循环在页面中渲染。
这里还涉及添加标签的操作,当用户点击标签时,标签转化为文本框供用户输入,当鼠标移开之后则变为tag的形状。
这里会遇到一个问题,当我们打开两个两个参数的展开列时,点击new tag标签,两个参数的标签都会变成文本框,并且如果用户输入文字的话,两个文本框会同步,这是因为他们其实共用了visible和value属性,我们要把这俩玩意区分开来,利用作用域插槽对其各自定义。
让文本框自动获得焦点:使用$nextTick 方法,其作用就是当页面上元素被重新渲染之后,才会执行回调函数中的代码,即this.$refs.saveTagInput.$refs.input.focus()。最后实现文本框的输入上传功能。
商品列表
跟以往一样我们需要从服务器中获取商品的数据并渲染到网页上,这里我们发现“创建时间”这一列展示是毫秒形式的时间,所有我们需要在main.js文件中自定义格式化时间的全局过滤器。
完成了分页功能、搜索功能,搜索功能就是调用一个getGoodsList函数即可。
添加商品需要一个新的页面,需要定义路由 this.$router.push('/goods/add')实现跳转
添加商品
渲染面包屑导航、步骤条、tab栏等组件,绘制一个级联选择器,且选择器只能选中3级商品
tab栏中阻止页签切换,通过在tabs标签中绑定一个:before-leave属性,为其指定一个函数,在函数中判断即将离开的标签页是否为0,且商品是否为三级分类,如果不是则返回false,组织切换标签。
切换页签时,当index是对应的索引时,显示对应的页面数据。
完成图片上传功能,值得注意的是在上传组件期间都要为上传组件手动指定headers请求头,同时在请求头对象中绑定Authorization字段,因为上传组件并没有调用axios,所以说需要手动指定字段。
图片上传成功之后,需要将图片的路径存放到一个pics数组中以便后续的上传商品信息,删除图片的话即删除对应的pics中的图片对象。
图片预览:有一个on:preview属性,函数体中我们将文件的url地址给previewPath,然后在img中src动态绑定这一地址。
富文本编辑器
首先在依赖中安装vue-quill-editor,然后在main.js中导入依赖,<quill-editor></quill-editor>
发起添加商品请求
这里老师讲到了有关深拷贝的问题,data中的数据与级联选择器中的数据格式不同会在发起添加请求时报错,当然这个问题现在element已经解决了,但是还是有学习一下深拷贝的,导入依赖lodash,使用_.cloneDeep()函数进行拷贝。
将发起添加商品服务器请求需要的数据都整理好完成添加商品请求,并通过路由跳转到商品界面。this.$router.push('/goods')
订单列表
省市区模块的联动效果
点击修改按钮会出现修改地址的对话框,对话框的具体功能就不一一实现了,我们这里就选择做省市区模块,需要在网上找一个citydata.js文件并导入,在级联选择器中的:option选项所指向的就是这个文件的内容。
物流进度以一个时间线的形式展示出来
<el-timeline>
<el-timeline-item v-for="(activity, i) in progressInfo" :key="i" :timestamp="activity.time">{{activity.context}</el-timeline-item>
</el-timeline>
数据报表功能开发
基于E charts绘制图形区域,安装echarts依赖,仿照官方文档绘制报表
优化上线
页面加载过程进度条,安装nprogress依赖并导入main文件,配置两个拦截器,request,response拦截器