第七天学习总结—员工模块1

目标:点击左侧员工姓名实现高亮,右侧显示选中的对应员工信息

1、树形结构

//封装一个将列表结构的数据转换为树形结构的数据
default-expand-all:定义树形结构是否展开 默认展开
expand-on-click-node:设置点击一个节点的文字下拉信息不收起, 默认收起
highlight-current:点击当前节点的时候是否高亮;默认不高亮

**注意点:**
上面三个属性值设置的时候有两种方式:
// 一、动态绑定之后设置值true或者false
  <el-tree 
      :default-expand-all="true"
      :expand-on-click-node="false"
      :highlight-current="true"
  />
  

// 二、若属性值为true直接将属性放入标签即可,不需要额外的数据绑定赋值
      <el-tree 
          highlight-current 
          default-expand-all
      />
      
// 三、以下写法是错误的(下图是报错的截图)
      <el-tree
          highlight-current="true"
          default-expand-all="true"
      />

Snipaste_2023-05-31_10-28-30.png

2、员工管理—初始化首个节点高亮状态

添加属性node-key="id" 前面不加冒号: a.定义一个变量queryParams: { departmentId: null } b.通过setCurrentKey配合node-key c.vue的渲染是异步的,涉及到等待机制,所以需要通过this.$nextTick进行数据设置 nextTick本质还是定时器,只不过是等待上面的步骤执行完了,没有设置时间罢了,然后调用forceUpdate手动让页面再次渲染。

// 初始化数据
    async getDepartmentList() {
      const res = await departs()
      this.departs = translateListToTreeData(res, 0)
      this.queryParams.departmentId = this.departs[0].id

      this.$nextTick(() => {
        this.$refs.treeRef.setCurrentKey(this.queryParams.departmentId)
      })
    }

3、点击员工的时候将此节点的id赋值给this.queryParams.departmentId

    currentChange(node) {   // node为当前选中接待的信息  — 一个对象
        this.queryParams.departmentId = node.id
    }

4、获取员工信息

这里员工信息的获取需要在左侧部门数据渲染之后在进行调用接口

Snipaste_2023-05-31_12-08-55.png

5、点击左侧右侧对应员工信息显示

<el-tree @current-change="currentChange">

currentChange(node) {
  this.queryParams.departmentId = node.id
  this.getEmployeeList()
}

5、将后台返回的图片路径转换为图像(el-Avatar头像组件)

这里用到了elementui提供的插槽再配合v-if对图像的路径是否存在进行判断,有的话直接展示图像,没有的话显示人名的姓氏,这个涉及到获取第一个字符串的方法charAt(),它默认获取第一个字符串,所以不写0也可以。

Snipaste_2023-05-31_15-15-04.png

6、员工分页处理

// 这个需求涉及到了三个属性:
page(当前页码) 
pagesize(当前页码有多少页)
total(数据总条数)
此外,还涉及到一个改变页码的事件current-change 这个事件在触发的时候会携带当前页码

这个地方有个注意点就是:在点击左侧的部门进行切换的时候,需要将当前的页码设置为1

7、搜索员工涉及到的知识点

  • 防抖处理 首先我们需要给输入框绑定input事件,但是这样会导致在输入值的时候对后端过多的请求,为提升性能,我们需要对这一情况做防抖处理。具体做法是:将业务代码放入延时器中,同时延时器向外暴露它的id => this.timer,在延时器代码执行之前我们先清除this.timer,这样就实现了防抖处理。

  • change和input两个事件的区别:

    • change:仅在输入框失去焦点或用户按下回车时触发
    • input:在input值改变的时候触发
  • 为何不在data里面设置timer,而是用this.timer data里面的数据都是响应式的,这里的timer只需要接收延时器的id,然后每次调用接口之前只需要对这个做清除处理即可。这样做能提升性能。

  • 防抖(debounce)和节流(throttle)的区别

    • 防抖:就是指触发事件后 n 秒后才执行函数,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。
    • 节流:指连续触发事件但是在 n 秒中只执行一次函数
  • 防抖和节流的应用场景

    • 防抖:1、用户在不断输入值时,用防抖来节约请求资源。2、- window触发resize的时候,不断的调整浏览器窗口大小会不断的触发这个事件,用防抖来让其只触发一次
    • 节流:1、鼠标不断点击触发,mousedown(单位时间内只触发一次);2、监听滚动事件,比如是否滑到底部自动加载更多,用throttle来判断

8、员工导出Excel

  • 调用接口 => 返回的是二进制流数据
  • 在拦截器中判断类型 if(response.data instanceof Blob) return response.data
  • 获取二进制流文件:通过调用接口获取二进制流文件
  • 通过FileServer插件将文件导出 FileServer.saveAs(res, '员工测试表.xlsx')
Snipaste_2023-05-31_17-19-46.png Snipaste_2023-05-31_17-18-31.png Snipaste_2023-05-31_17-22-12.png

这里需要npm i file-saver 插件并引入

如何实现初始化和点击左侧部门高亮状态效果的逐字稿:

  1. 在获取左侧部门数据之前,我们先定义一个对象:queryParams: { departmentId: null }.这个对象的值初始为null。他是为了保存初始化和点击左侧部门时的id

  2. 为了提升界面的体验,我们需要给el-tree设置对应的属性

    default-expand-all:定义树形结构是否展开 默认展开 expand-on-click-node:设置点击一个节点的文字下拉信息不收起, 默认收起 highlight-current:点击当前节点的时候是否高亮;默认不高亮

  3. 初始化通过elementUi库提供的api setCurrentKey配合node-key给顶级部门设置高亮状态。这里涉及到了vue的异步操作,需要使用vue提供的this.$nextTick()方法进行处理。

  4. 点击左侧部门,右侧对应的数据显示。在点击右侧部门的时候,elementui提供的点击事件会向外暴露出当前部门的信息,包括Id,我们可以通过将这个id赋值给定义好的this.queryParams.departmentId然后再执行this.getEmployeeList()即可。

Snipaste_2023-05-31_15-23-31.png

9、左树右表的实现思路

  • 左树

    • 列表数据=>树形数据
      • 我们使用到el-tree组件,但是这个组件接收的数据是树形数据,而后端返回的是列表数据,所以我们需要通过递归的方法将列表数据转换为树形数据。
    • 初始化顶级pid高亮显示
      • 首先初始化记录部门的id,然后配合elementui里面的setCurrentPage和node-key方法进行实现。因为里面涉及到异步操作,所以我们需要用到vue里面提供的$nextTick方法。
  • 右表

    • 通过el-tabl进行员工的信息渲染,通过el-pagination进行列表数据的相应切换。这里设计的用户图像的显示和聘用形式格式的转换。图像我用作用域插槽暴露每行数据,el-avatar组件配合实现,若获取不到员工的图像,这使用charAt()方法获取员工的姓加上相应的样式替代图片进行显示。
  • 左树右表的切换实现思路

    • 首先将当前的页码设置为1
    • 将当前行的员工id赋值给初始化记录部门的id,通过这个id获取相应的员工数据并进行渲染

10、针对搜索模块是如何进行优化的

答:在输入框进行数据输入的时候,需要实时向后端请求数据。但是这样对后端接口有很大的压力,我们可以通过防抖的方式进行优化处理。防抖的核心是利用setTimeout延时器进行相应的业务操作。

11、员工导出excel的实现步骤

  • 首先我们要封装一个下载模板接口的api,这个api与其他封装的api不同点在于它设置了一个接收数据的类型 responseType: 'blob' 意思是:使用blob接收二进制文件流。
  • 安装插件file-saver,然后通过这个插件将调用接口返回来的数据进行处理可下载的xlsx文件。
  • 处理报错;因为二进制流文件返回的数据里面没有message这个属性,所以我们需要通过instanceof对返回的数据进行相应的处理,判单是否为blob类型,即:if(response.data instanceof Blob) return response.data。这样就解决了报错问题。

12、Excel组件封装

Snipaste_2023-06-01_10-05-43.png
  • 这个组件里面有个值得学习的方法,他将事件直接写在了组件内部

    fcadfcabfc4ca16a98cd27af59547d2.png
  • 封装接口接收返回的类型binary => 二进制流数据

    9723cdb82a535399fad3406cc67e1ec.png
  • 点击导出配合FileSaver插件进行文件生成和导出

    978d9bd41988f21ce45f68c6c5553dc.png

13、员工导入

Snipaste_2023-06-01_10-31-00.png

  • 在type类型为file的input输入框里面,她有个属性accept用来设置输入文件的类型:accept=".xlsx, .xls"
  • 获取短号拼接的ref值的组件,this.$refs['excel-upload-input']
91461fdf1742f857fa7cd1108d2c6eb.png
  • 涉及到文件上传的数据类型都为form-data

    1685588183702.png

1685590258781.png

逐字稿:

  • 点击导入按钮触发文件选择按钮的click事件
  • 选择文件触发input的change事件
  • 通过event接收选中的文件信息,并哟个files进行保存
  • 为避免不必要的bug我们需要对files的长度进行判断
  • new一个FormData()对象并将获取到的文件信息append进去
  • 然后将这个对象传递到后端去
  • 通知父组件关闭弹窗
  • 通过try获取成功或者失败的信息,无论成功与否都将input里面的值清空,这个可以放入finally里面进行处理。

14、员工详情

  • 数据和校验 model整个表单的数据 rules指规则

  • 路由配置注意点:两种配置方法

    e9b6e4f57511ab72c26a4e89cacae7f.png
  • 组件el-select使用的注意事项:

    option里面的value是传给后端的值,label是在界面显示的值

    Snipaste\_2023-06-01\_17-31-58.png
  • 组件el-date-picker中,添加value-format="yyyy-MM-dd"可以设置时间格式为 2023-06-23 Snipaste\_2023-06-01\_17-43-19.png

15、级联组件 el-cascader

  • 知道里面的三个参数:

    • options:绑定数据

    • props:自定义绑定的数据属性

    • separator="-" 自定义数据间隔的属性

      Snipaste_2023-06-01_17-52-03.png

  • 使用的步骤

    • 从接口获取数据

    • 将列表数据转为树形数据

      Snipaste_2023-06-01_17-59-49.png
    • 此组件使用的是 value label,而后端返回的数据是id和name,所以需要通过props重置属性为:id和name

    Snipaste_2023-06-01_18-03-41.png

    Snipaste_2023-06-01_18-09-32.png

    • 将数据赋值给treeData
    Snipaste_2023-06-01_18-11-30.png

至此,el-cascader组件使用完成。

这就是员工模块的技术总结。本人能力有限,不足之处还望多多指教~