10.人力资源管理项目 -_员工详情==>页面和路由、布置个人详情、图片存储、腾讯云cos申请、图片上传组件Upload的二次封装、图片上传进度条、全局图片组件
在创建页面和路由时,千万要记得加上hidden属性,不然会产生二级菜单。
在布局个人详情时,之前我们遇到的表单大多是竖着排列的,而这一次分成了左右两列。我们可以通过element-ui中Layout布局中的el-row和el-col来实现这种布局,将每一行用el-row隔开,然后再在el-row中等分el-col(设置:span=12,因为总共为24分,设置12即为平均等分)。
在个人详情布局页面中,发现了一个bug,那就是聘用形式无法回显,即更改后虽然在调试工具中显示值已经变化,但是页面中却并没有变化。原因是直接赋值时数据劫持丢失,解决方式是改用$set()来处理;
在保存更新时,日期选择部分出了问题,原因是我们手动添加了
value-format
这个方法,这个方法会导致保存的数据类型发生改变,而我们保存的操作会用到date数据类型中的方法,而el-date-picker
的默认绑定格式(不写时)就是date日期对象,因此解决方法很简单,直接删掉value-format
这一行就行。
01.员工详情-页面和路由
目标
- 创建 员工详情 的布局页面
- 创建 员工详情 的路由跳转
讲解
分析
- 使用 el-tabs 组件完成整体的结构
- 三个子模块的功能通过三个独立的组件来实现
实现
-
页面结构搭建
-
把页面放在
views/employees/detail.vue
,因为这个页面还是与员工相关的,所以仍放置在employees目录下<template> <div class="employees-container"> <div class="app-container"> <el-card> <el-tabs> <el-tab-pane label="登录账户设置"/> <el-tab-pane label="个人详情" /> <el-tab-pane label="岗位信息" /> </el-tabs> </el-card> </div> </div> </template>
-
在文件
router/modules/employees.js
绑定路由,因为员工详情页属于员工模块,所以直接和列表路由写到一起export default { path: '/employees', // 员工 component: Layout, children: [ { path: '', name: 'Employees', component: () => import('@/views/employees'), meta: { title: '员工', icon: 'people' } }, { path: 'detail', name: 'employeesDetail', component: () => import('@/views/employees/detail'), // 路由懒加载 hidden: true } ] }
-
在员工列表页面路由跳转到员工详情,需要携带了必要的 id 参数
<el-table-column label="操作" width="200"> <template slot-scope="scope"> <el-button type="text" size="small" @click="$router.push('/employees/detail?id=' + scope.row.id)" > 查看 </el-button> <el-button type="text" size="small">分配角色</el-button> <el-button type="text" size="small" @click="delEmp(scope.row.id)">删除</el-button> </template> </el-table-column>
小结
-
为什么这个详情可以放到children里了?
答案
- 因为详情页面不需要左侧导航了, 而且作为二级路由可以在右下角查看, 而且hidden也为true了
02.员工详情-将组件拆分维护
目标
按照不同 tab 创建不同的内容组件
分析
根据分析,这里把三个面板中的内容分别拆成三个对应的组件
实现
-
登录账号设置组件
src\views\employees\detail\login-setting.vue
<template> <div class="login-setting"> 账号设置 </div> </template> <script> export default { name: 'LoginSetting' } </script> <style lang="scss" scoped></style>
-
src\views\employees\detail\user-info.vue
员工个人信息组件<template> <div class="user-info"> 个人信息 </div> </template> <script> export default { name: 'UserInfo' } </script> <style lang="scss" scoped></style>
-
src\views\employees\detail\job-info.vue
员工工作信息组件<template> <div /> </template> <script> export default { name: 'JobInfo' } </script> <style lang="scss" scoped></style>
-
把上面定义的三个组件引入到 detail.vue 中,并使用
<template> <div class="employees-container"> <div class="app-container"> <el-card> <el-tabs> <el-tab-pane label="登录账户设置"> <login-setting /> </el-tab-pane> <el-tab-pane label="个人详情"> <user-info /> </el-tab-pane> <el-tab-pane label="岗位信息"> <job-info /> </el-tab-pane> </el-tabs> </el-card> </div> </div> </template> <script> // 导入子组件 import JobInfo from './detail/job-info' import LoginSetting from './detail/login-setting' import UserInfo from './detail/user-info' export default { // 挂载子组件 components: { JobInfo, LoginSetting, UserInfo } } </script> <style lang="scss" scoped> </style>
小结
-
我们为什么把3个tab-pane的内容, 封装分散出独立的组件?
答案
- 因为这样便于复用和管理
03.员工详情-帐户设置页面布局
目标
- 完成登录帐户设置页面布局
- 完成登录账号设置页面数据渲染
分析
- 页面结构使用 Form 表单实现
- 封装帐户设置的请求 api
- 进行数据回填
实现
-
静态结构使用 Form 组件实现
<template> <div class="login-setting"> <el-form ref="userForm" :model="userInfo" label-width="120px" style="margin-left: 120px; margin-top: 30px" > <el-form-item label="姓名:"> <el-input v-model="userInfo.username" style="width:300px" /> </el-form-item> <el-form-item label="密码:"> <el-input v-model="userInfo.password" type="password" style="width:300px" /> </el-form-item> <el-form-item> <el-button type="primary">更新</el-button> </el-form-item> </el-form> </div> </template> <script> export default { name: 'LoginSetting', data() { return { userInfo: { username: '', password: '' } } } } </script> <style lang="scss" scoped></style>
-
在
src\api\user.js
封装请求api/** * @description: 获取员工详细信息 * @param {*} id 用户id * @return {*} */ export function getUserDetailByIdAPI(id) { return request({ url: `/sys/user/${id}` }) }
-
在
employees/components/login-setting.vue
中导入 API- 获取数据,保存到数据项
- 数据项显示到视图
import { getUserDetailByIdAPI } from '@/api' export default { name: 'LoginSetting', data() { return { userInfo: { username: '', password: '' } } }, created() { // 调用获取用户详情的方法 this.loadUserDetailById() }, methods: { // 获取用户详情 async loadUserDetailById() { const res = await getUserDetailByIdAPI(this.$route.query.id).catch(err => err) if (!res.success) return this.$message.error(res.message) this.userInfo = res.data } } }
小结
-
账户如何做回显?
答案
- 跳转到查看页面传递用户的id, 请求详细信息, 然后放置到表单对象里显示页面
04.员工详情-修改用户名和密码
目标
用户更改用户名或密码后,点击保存,实现用户名和密码修改
分析
- 封装修改用户名和密码的 api
- 当用户点击更新,调用 api,修改用户名和密码
实现
-
在
src/api/employees.js
中,封装修改信息 api 用来获取保存新的数据/** * @description: 保存员工信息 * @param {*} data * @return {*} */ export function saveUserDetailByIdAPI(data) { return request({ url: `/sys/user/${data.id}`, method: 'put', data }) }
-
在**
src/views/employees/detail/login-setting.vue
** 组件中添加表单校验<template> <div class="login-setting"> <el-form ref="userForm" :model="userInfo" :rules="rules" label-width="120px" style="margin-left: 120px; margin-top: 30px" > <el-form-item label="姓名:" prop="username"> <el-input v-model="userInfo.username" style="width:300px" /> </el-form-item> <el-form-item label="密码:" prop="password"> <el-input v-model="userInfo.password" type="password" style="width:300px" /> </el-form-item> <el-form-item> <el-button type="primary" @click="updateUser">更新</el-button> </el-form-item> </el-form> </div> </template> <script> import { getUserDetailByIdAPI, saveUserDetailByIdAPI } from '@/api/user' export default { name: 'LoginSetting', data() { return { userInfo: { username: '', password: '' }, rules: { username: [{ required: true, message: '用户名不能为空', triggler: 'blur' }], password: [{ required: true, message: '密码不能为空', triggler: 'blur' }] } } }, // 其他代码略…… }
-
在组件中调用 api,实现修改功能
import { getUserDetailById, saveUserDetailByIdAPI } from '@/api/user' export default { name: 'LoginSetting', data() { return { userInfo: { username: '', password: '' }, rules: { username: [{ required: true, message: '用户名不能为空', trigger: 'blur' }], password: [{ required: true, message: '密码不能为空', trigger: 'blur' }] } } }, created() { // 调用获取用户详情的方法 this.loadUserDetailById() }, methods: { // 更新用户信息模块 updateUser() { this.$refs.userForm.validate(async valid => { if (!valid) return this.$message.error('检查用户名和密码') const res = await saveUserDetailByIdAPI(this.userInfo) this.loadUserDetailById() this.$message.success(res.message) }) }, // ...其他 } }
小结
-
如何更新用户名和密码?
答案
- 把表单当前数据, 传入更新接口调用
05.员工详情-个人详情页面布局
目标
实现个人信息的读取及显示
页面结构
-
封装接口,获取个人信息数据
-
页面结构绘制
-
实现页面的渲染
<template> <div class="user-info"> <!-- 个人信息 --> <el-form label-width="220px"> <!-- 工号 入职时间 --> <el-row class="inline-info"> <el-col :span="12"> <el-form-item label="工号"> <el-input v-model="userInfo.workNumber" class="inputW" /> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="入职时间"> <el-date-picker v-model="userInfo.timeOfEntry" style="width: 300px" type="date" class="inputW" /> </el-form-item> </el-col> </el-row> <!-- 姓名 部门 --> <el-row class="inline-info"> <el-col :span="12"> <el-form-item label="姓名"> <el-input v-model="userInfo.username" class="inputW" /> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="部门"> <el-input v-model="userInfo.departmentName" class="inputW" /> </el-form-item> </el-col> </el-row> <!--手机 聘用形式 --> <el-row class="inline-info"> <el-col :span="12"> <el-form-item label="手机"> <el-input v-model="userInfo.mobile" style="width: 300px" /> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="聘用形式"> <el-select v-model="userInfo.formOfEmployment" class="inputW"> <el-option v-for="item in EmployeeEnum.hireType" :key="item.id" :label="item.value" :value="item.id" /> </el-select> </el-form-item> </el-col> </el-row> <!-- 员工照片 --> <el-row class="inline-info"> <el-col :span="12"> <el-form-item label="员工头像"> <!-- 放置上传图片 --> </el-form-item> </el-col> </el-row> <!-- 保存个人信息 --> <el-row class="inline-info" type="flex" justify="center"> <el-col :span="12"> <el-button type="primary" @click="saveUser">保存更新</el-button> <el-button @click="$router.back()">返回</el-button> </el-col> </el-row> </el-form> </div> </template> <script> import { getUserDetailByIdAPI } from '@/api/user' import EmployeeEnum from '@/api/constant/employees' export default { data() { return { userId: this.$route.query.id, EmployeeEnum, // 员工枚举数据 userInfo: {} } }, created() { // 调用获取用户信息的 API this.loadUserInfoById() }, methods: { async loadUserInfoById() { const res = await getUserDetailByIdAPI(this.userId).catch(err => err) if (!res.success) return this.$message.error(res.message) this.userInfo = res.data }, saveUser() {} } } </script> <style scoped lang="scss"> .user-info{ padding-top:20px; } </style>
暂时没有设置图片
-
tips:有问题—》 聘用形式出了问题,无法回显 ------>> 原因:在请求返回的数据中根本没有我们想要的formOfEmployment
解决方法:将formOfEmployment在父组件中传入
<el-table-column prop="" label="操作" width="280"> <template v-slot="scope"> <el-button type="text" size="small" @click="$router.push(`/employees/detail?id=${scope.row.id}&formOfEmployment=${scope.row.formOfEmployment}`)" >查看</el-button> <el-button type="text" size="small">分配角色</el-button> <el-button type="text" size="small" @click.native="delEmp(scope.row.id)">删除</el-button> </template> </el-table-column>
然后在子组件中赋值:
async loadUserInfoById() { const res = await getInfo(this.userId).catch(err => err) if (!res.success) return this.$message.error(res.message) this.userInfo = res.data this.userInfo.formOfEmployment = parseInt(this.$route.query.formOfEmployment) },
但是还是有问题!!
我们发现此时无法修改聘用形式这一栏 ----> 经过观察在我们点击选项时vue中的数据发生了改变,但没有更新到视图中,是数据劫持出了问题!
解决方式:改用$set():
async loadUserInfoById() { const res = await getInfo(this.userId).catch(err => err) if (!res.success) return this.$message.error(res.message) this.userInfo = res.data // this.userInfo.formOfEmployment = parseInt(this.$route.query.formOfEmployment) this.$set(this.userInfo, 'formOfEmployment', parseInt(this.$route.query.formOfEmployment)) },
小结
-
个人详情布局如何做?
答案
- 传递id到详情页面, 然后请求数据铺设页面
06.员工详情-个人详情保存更新
目标
保存个人信息
分析
- 表单验证
- 点击保存,调用接口
代码
-
封装保存用户信息的 API
/** * 保存员工的基本信息 * @param {*} data * @returns */ export function saveUserDetailByIdAPI(data) { return request({ url: `/sys/user/${data.id}`, method: 'put', data }) }
-
导入 API
import { saveUserDetailByIdAPI } from '@/api/employees'
-
点击保存,更新用户个人详情
methods: { // 保存用户信息的更改 async saveUser() { const res = await saveUserDetailByIdAPI(this.userInfo) if (!res.success) return this.$message.error(res.message) this.loadUserInfoById() this.$message.success(res.message) } }
-
日期问题处理:当我们选择日期时会报错!!
原因:
小结
-
个人信息保存更新思路是?
答案
- 把表单的数据传递给更新数据的接口
07.员工详情-图片存储方案介绍
目标
了解主流的图片存储方案
两种常见方案
1. 存到自己公司购买的服务器上
优点:好控制
缺点:成本高由于图片都存放到自己的服务器上,占据空间很大
2. 存到三方云服务器(阿里云,七牛云,腾讯云)
各种云有专门的为图片存储提供的云服务器,我们自己的服务器只存储图片地址即可
上面属于第三方图片服务器, 直传
还有一种是把图片文件传给自己的后台, 由后台上传到第三方图片服务器
小结
-
我们上传图片有几种方案?
答案
- 前端直传第三方图片托管服务器, 或者前端传给后端, 后端传递图片到第三方图片托管服务器, 或者我们服务器自己存储, 比较占用服务器资源
08.员工详情-腾讯云cos申请配置
目标
使用现成的腾讯云服务创建一个免费的云存储。
创建账号并实名认证
- 打开腾讯云,点击右上角登录,使用微信扫码进行登录
- 注册或关联账号
- 提示关注腾讯云并完成账号注册
- 注册完成
- 点击去实名认证,选择个人认证,进行实名认证
开通对象存储
创建存储桶
剩下几步默认下一步就行了
设置cors规则
在存储桶列表中,选中存储桶
在左侧的菜单中选安全管理
因为我们是在测试上传,全部容许上传即可,真正的生产环境需要单独配置具体的域名和操作方法
配置云API秘钥
服务器属于个人的,需要一定的权限才能自由上传图片,这个负责权限验证的其实就是秘钥,也就是说拥有秘钥是进行上传的必要条件。
秘钥配置和API密钥管理
安全性提示
实际工作中,秘钥属于敏感信息,不能直接放到前端存储,容易产生安全问题,更好的做法是把秘钥交给后端管理,前端通过调用接口先获取秘钥,有了秘钥之后再进行上传操作
以上我们就完成了,所有的准备工作~
小结
-
我们刚才做的一些操作目的是什么?
答案
09.员工详情-图片上传组件封装思路
目标
了解图片上传组件实现的思路
分析
重点
- 前端主动发起图片上传使用的是三方的腾讯云上传接口
- 前端得到一个已经上传完毕的图片地址
- 然后把这个地址当成一个接口字段 传给我们自己的后端服务
小结
-
我们前端把图片到底传递到了哪里?
答案
- 上传到了第三方云服务器上
10.员工详情-二次封装 Upload 上传
目标
基于 element 框架提供的 Upload 上传组件封装自己的上传组件
思路
- 创建自定义上传组件
- 分析 element 中的 Upload 上传组件
- 将 element 中的 Upload 上传组件进行封装
实现
-
创建
src\components\UploadImg\index.vue
组件 -
将 element 中的 Upload 上传组件进行封装
<template> <div> <el-upload class="avatar-uploader" action="https://jsonplaceholder.typicode.com/posts/" :show-file-list="false" :on-success="handleAvatarSuccess" :before-upload="beforeAvatarUpload" > <img v-if="imageUrl" :src="imageUrl" class="avatar"> <i v-else class="el-icon-plus avatar-uploader-icon" /> </el-upload> </div> </template> <script> export default { name: 'UploadImg', data() { return { imageUrl: '' } }, methods: { handleAvatarSuccess(res, file) { this.imageUrl = URL.createObjectURL(file.raw) }, beforeAvatarUpload(file) { const isJPG = ['image/jpeg', 'image/png', 'image/jpg', 'image/gif'].includes(file.type) const isLt2M = file.size / 1024 / 1024 < 2 if (!isJPG) { this.$message.error('上传头像图片只能是 JPG 格式!') } if (!isLt2M) { this.$message.error('上传头像图片大小不能超过 2MB!') } return isJPG && isLt2M } } } </script> <style> .avatar-uploader .el-upload { border: 1px dashed #d9d9d9; border-radius: 6px; cursor: pointer; position: relative; overflow: hidden; } .avatar-uploader .el-upload:hover { border-color: #409EFF; } .avatar-uploader-icon { font-size: 28px; color: #8c939d; width: 160px; height: 160px; line-height: 178px; text-align: center; } .avatar { width: 178px; height: 178px; display: block; } </style>
-
配置自定义上传属性
- 关键属性:
:http-request="upload" action="#"
- 使用自定义行为覆盖默认上传,注意一旦设置自定义上传行为之后,所有的上传操作都需要自己实现,比如数据处理,上传成功之后的后续操作,on-success 钩子函数也不会继续触发
<template> <div> <el-upload class="avatar-uploader" action="#" :show-file-list="false" :on-success="handleAvatarSuccess" :before-upload="beforeAvatarUpload" :http-request="upload" > <img v-if="imageUrl" :src="imageUrl" class="avatar"> <i v-else class="el-icon-plus avatar-uploader-icon" /> </el-upload> </div> </template> <script> export default { name: 'UploadImg', methods: { // 自定义上传属性 upload(file) { console.log(file) }, // 其他略…… } } </script>
- 关键属性:
-
挂载为全局组件
import PageTools from './PageTools' import UploadExcel from './UploadExcel' import UploadImg from './UploadImg' export default { install(Vue) { // 注册工具栏组件 Vue.component('PageTools', PageTools) // 注册导入excel组件 Vue.component('UploadExcel', UploadExcel) // 挂载为全局组件 Vue.component('UploadImg', UploadImg) } }
-
在
src\views\employees\components\user-info.vue
组件中进行使用<!-- 员工照片 --> <el-row class="inline-info"> <el-col :span="12"> <el-form-item label="员工头像"> <!-- 放置上传图片 --> <upload-img /> </el-form-item> </el-col> </el-row>
小结
-
我们上传Upload组件使用的是哪个标签?
答案
- el-upload上传组件, 把它封装成components/UploadImg组件进行复用
11.员工详情-上传图片到腾讯云
目标
- 使用用腾讯云对象存储功能,将图片上传到腾讯云
- 根据 cos 的上传 API 实现上传功能
分析
-
在云服务器上的准备:申请 cos 服务器,配置密钥,设置cors访问
-
在代码层面的准备:
- 对象存储-接口文档
- 下载一个官方提供的操作cos服务的包(cos-js-sdk-v5)
- 用自己的密钥去实例化cos
- 具体做上传
实现
-
安装依赖
npm i cos-js-sdk-v5 --save
-
在
src/components/UploadImg/index.vue
实例化 cos 对象 // 导入 cos 模块 const COS = require('cos-js-sdk-v5') // SECRETID 和 SECRETKEY请登录 https://console.cloud.tencent.com/cam/capi 进行查看和管理 var cos = new COS({ SecretId: 'xxx', SecretKey: 'xxx' }) export default {}
-
使用 cos 对象完成上传
methods: { // 自定义上传属性 upload(res) { if (res.file) { cos.putObject({ Bucket: 'xxx', // 存储桶的名称,必须 Region: 'xxx', // 存储桶所在地域,必须字段 Key: res.file.name, // 文件名,必须 StorageClass: 'STANDARD', // 上传模式, 标准模式 Body: res.file, // 上传文件对象 // 上传进度条 onProgress: function(progressData) { console.log(JSON.stringify(progressData)) } }, (err, data) => { if (err === null && data.statusCode === 200) { this.imageUrl = `https:${data.Location}` } }) } } }
-
如何查看 Bucket 和 Region
小结
-
如何使用腾讯云上传图片呢?
答案
- 使用腾讯云的SDK软件开发工具包, 然后用他们内置的方法, 设置相关参数直接传递给服务器
12.员工详情-更新用户资料数据
目标
实现用户头像的更新
分析
- 目前头像的地址在
src\components\UploadImg
组件中 - 需要将图片地址,传递给父组件
- 通过 ref 获取到子组件实例,从而获取到用户头像地址
- 在将图片传递到服务器以后,当打开个人详情页面时需要做数据回显处理
实现
-
在
employees\detail\user-info.vue
组件中获取用户头像地址不要忘记给upload-img组件添加imageUrl属性哟
async saveUser() { // 获取到子组件中的图片地址 const newimageUrl = this.$refs.imageUrl.imageUrl this.userInfo.staffPhoto = newimageUrl const res = await saveUserDetailByIdAPI(this.userInfo) if (!res.success) return this.$message.error(res.message) this.loadUserInfoById() this.$message.success(res.message) }
-
在
employees\detail\user-info.vue
组件中将接口返回的图片回显给图片组件async loadUserInfoById() { const res = await getUserDetailByIdAPI(this.userId).catch(err => err) if (!res.success) return this.$message.error(res.message) this.userInfo = res.data // 将接口返回的图片赋值给图片组件 this.$refs.imageUrl.imageUrl = res.data.staffPhoto }
小结
-
图片保存的思路是什么?
答案
- 前端使用el-upload组件, 选择文件上传得到图片文件对象
- 把文件使用腾讯云的SDK上传到腾讯云的对象存储空间内, 返回一个腾讯云上的图片的地址
- 然后保存到UploadImg组件内变量上, 点击更新按钮, 拿到图片地址和表单其他数据, 更新到自己的后台保存即可(保存的是图片的地址而不是图片文件本身呦)
13.员工详情-实现图片上传进度条功能
目标
在图片上传的过程中,显示图片上传的进度条
分析
-
在上传时,cos 支持配置 onProgress 回调,在这个回调函数中可以拿到当前上传的进度
// 自定义上传属性 upload(res) { if (res.file) { cos.putObject({ Bucket: 'xxx', // 存储桶的名称,必须 Region: 'xxx', // 存储桶所在地域,必须字段 Key: res.file.name, // 文件名,必须 StorageClass: 'STANDARD', // 上传模式, 标准模式 Body: res.file, // 上传文件对象 // 上传进度条 onProgress: function(progressData) { console.log(JSON.stringify(progressData)) } }, (err, data) => { if (err === null && data.statusCode === 200) { this.imageUrl = `https:${data.Location}` } }) } }
-
进度条的显示使用 Element 提供的
Progress 进度条
组件
实现
-
更改组件结构,添加
Progress 进度条
组件src/components/UploadImg/index.vue
<el-upload class="avatar-uploader" action="#" :show-file-list="false" :on-success="handleAvatarSuccess" :before-upload="beforeAvatarUpload" :http-request="upload" > <img v-if="imageUrl" :src="imageUrl" class="avatar"> <i v-else class="el-icon-plus avatar-uploader-icon" /> <el-progress v-if="showProgress" type="circle" :percentage="100" class="progress" /> </el-upload> <style> .progress { position: absolute; display: flex; top: 50%; left: 50%; transform: translate(-50%, -50%); background: #e4e4e4; border-radius: 50%; opacity: 0.9; } </style>
-
在 data 字段中添加
percent
字段data() { return { percent: 0, // 图片的上传进度 showProgress: false // 是够显示上传进度 } }
-
在 cos 实例的
onProgress
回调函数中获取到进度并赋值给 percentmethods: { // 自定义上传属性 upload(res) { if (res.file) { // 显示进度条 this.showProgress = true cos.putObject( { Bucket: 'long-1258431239', // 存储桶的名称,必须 Region: 'ap-beijing', // 存储桶所在地域,必须字段 Key: res.file.name, // 文件名,必须 StorageClass: 'STANDARD', // 上传模式, 标准模式 Body: res.file, // 上传文件对象 // 上传进度条 onProgress: (progressData) => { // 控制进度条的进度 this.percent = progressData.percent * 100 } }, (err, data) => { if (err === null && data.statusCode === 200) { this.imageUrl = `https:${data.Location}` // 隐藏进度条 this.showProgress = false } } ) } } }
小结
-
图片上传进度条如何做的?
答案
- 上传有个方法叫onProgress, 然后使用el-progress组件, 设置百分比值即可
14.员工列表-在员工列表中显示头像
目标
在表格中显示员工头像
思路
通过自定义列,将图片显示在表格中
操作
-
在
src\views\employees\index.vue
中的 table 上补充一列<el-table-column label="头像" width="120"> <template slot-scope="scope"> <img class="staffPhoto" :src="scope.row.staffPhoto"> </template> </el-table-column>
-
样式调整
<style lang="scss" scoped> .staffPhoto { width: 100px; height: 100px; border-radius: 50%; } </style>
-
此时可能部分图片无法正常显示(原因是图片本身地址有误,或者就是没有设置图片)
小结
-
为什么有的图片没有了?
答案
- 此时可能部分图片无法正常显示(原因是图片本身地址有误,或者就是没有设置图片)
15.通用封装-封装全局图片组件
目标
封装全局图片组件,实现两个效果:
- 没有src属性时,有一个默认图片
- 统一样式
分析
-
首先需要封装图片组件,然后进行全局注册
- 使用 Element 提供的 Image 图片
-
在业务组件使用封装的组件
- 组件使用者如果传递了图片,使用传递的图片
- 如果没有传递图片,使用默认图片
实现
-
新建组件
src\components\ImageHolder\index.vue
把素材里的img文件夹, 放到
src\components\ImageHolder下面
<template> <!-- el-image组件 :https://element.eleme.io/#/zh-CN/component/image --> <el-image :src="src" class="img-container"> <!-- error插槽:设置如果出错,要显示的内容 --> <template #error> <!-- 静态资源就近维护:把head.jpg这张图放在这个组件的目录下 --> <img src="./img/head.jpg" alt=""> </template> </el-image> </template> <script> export default { // 定义如何从父组件中接收数据 props: { src: { type: String, default: '' } } } </script> <style scoped lang="scss"> .img-container { border-radius: 50%; img { width: 100%; } } </style>
-
全局注册组件
import ImageHolder from './ImageHolder' export default { install(Vue) { // 将图片组件挂载为全局组件 Vue.component('ImageHolder', ImageHolder) } }
-
在业务组件中封装组件
<el-table-column label="头像" width="120"> <template slot-scope="scope"> <image-holder class="staffPhoto" :src="scope.row.staffPhoto" /> </template> </el-table-column>
小结
-
我们为什么要封装图片组件
答案
- 可以统一设置, 然后统一使用