2023.7.13-人力资源后台管理系统

人力资源管理项目

2023.7.13-人力资源后台管理系统_第1张图片
2023.7.13-人力资源后台管理系统_第2张图片
2023.7.13-人力资源后台管理系统_第3张图片
2023.7.13-人力资源后台管理系统_第4张图片

准备工作

  1. 在文件资源管理器中shift+右键=>Powershell输入 git clone [email protected]:panjiachen/vue-admin-template.git hm-hr
    自动生成克隆文件夹在本地2023.7.13-人力资源后台管理系统_第5张图片

2023.7.13-人力资源后台管理系统_第6张图片

2023.7.13-人力资源后台管理系统_第7张图片

  1. 项目目录2023.7.13-人力资源后台管理系统_第8张图片
├── src                        # 源代码目录
│   ├── api                    # 所有请求
│   ├── assets                 # 主题 字体等静态资源
│   ├── components             # 全局公用组件
│   ├── icons                  # 项目所有 svg icons
│   ├── layout                 # 全局 layout
│   ├── router                 # 路由
│   ├── store                  # 全局 store管理
│   ├── styles                 # 全局样式
│   ├── utils                  # 全局公用方法
│   ├── views                  # views 所有页面
│   ├── App.vue                # 入口页面
│   ├── main.js                # 入口文件 加载组件 初始化等
│   └── permission.js          # 权限管理
│   └── settings.js            # 配置文件

  1. 将package.json中手动修改版本号 “core-js”: “3.6.5”=> “core-js”: “3.25.5”
  1. npm i

  2. npm run dev

  3. 删除main.js中的 mock2023.7.13-人力资源后台管理系统_第9张图片

  4. 全部删除2023.7.13-人力资源后台管理系统_第10张图片

  5. 部分删除2023.7.13-人力资源后台管理系统_第11张图片

  6. 部分删除
    2023.7.13-人力资源后台管理系统_第12张图片

  7. 部分删除
    2023.7.13-人力资源后台管理系统_第13张图片

  8. 重启项目 npm run serve 无报错

  9. 初始化仓库=>删除文件中的 .git(没有显示隐藏项目)2023.7.13-人力资源后台管理系统_第14张图片

  10. 初始化仓库=>完成项目的初始化2023.7.13-人力资源后台管理系统_第15张图片
    2023.7.13-人力资源后台管理系统_第16张图片

准备素材
  1. 素材2023.7.13-人力资源后台管理系统_第17张图片
  2. svg矢量文件,设置矢量图标, (电子电路领域) ,显示图标=>login页面可以看到效果图标
<svg-icon icon-class="password" />
      <svg-icon icon-class="bug" />
      <svg-icon icon-class="chart" />
      <svg-icon icon-class="404" />

2023.7.13-人力资源后台管理系统_第18张图片
查找svg-coin文件
2023.7.13-人力资源后台管理系统_第19张图片
svg组件
2023.7.13-人力资源后台管理系统_第20张图片

  1. svg组件2023.7.13-人力资源后台管理系统_第21张图片
  2. loader : 加载器=>处理其他文件(svg)的
    2023.7.13-人力资源后台管理系统_第22张图片
结构梳理

2023.7.13-人力资源后台管理系统_第23张图片
2023.7.13-人力资源后台管理系统_第24张图片

2023.7.13-人力资源后台管理系统_第25张图片

基础设置settings.js和导航守卫permission.js
  1. settings.js导出网站基础配置,包括: 网站标题、固定header、显示logo
  2. logopermission.js(权限),主要负责路由导航守卫
    2023.7.13-人力资源后台管理系统_第26张图片
    2023.7.13-人力资源后台管理系统_第27张图片
    2023.7.13-人力资源后台管理系统_第28张图片
//settings.js
module.exports = {

  title: 'Vue Admin Template',

  /**
   * @type {boolean} true | false
   * @description Whether fix the header
   */
  fixedHeader: true,

  /**
   * @type {boolean} true | false
   * @description Whether show the logo in sidebar
   */
  sidebarLogo: true
}

2023.7.13-人力资源后台管理系统_第29张图片

完成了user.js的配置

2023.7.13-人力资源后台管理系统_第30张图片
2023.7.13-人力资源后台管理系统_第31张图片

写登录模块

  1. 实现登录表单验证=>element-ui
  • 手动校验=>validate方法=>ref拿到表单实例$refs
  • 自动校验
跨域:协议,域名,端口号任意一个不一样就会发生跨域

2023.7.13-人力资源后台管理系统_第32张图片
2023.7.13-人力资源后台管理系统_第33张图片

  • 协议:http<==>https
  • 域名:localhost<==>heimahr.itheima.net
  • 端口号: 9528<==>443
    http协议默认端口号80(可省略)
    https默认端口443(可省略)

2023.7.13-人力资源后台管理系统_第34张图片
post会发生两次请求

  • 预检请求(Preflight Request)是在进行跨域资源共享(Cross-Origin Resource Sharing,CORS)时,浏览器发送的一种额外的HTTP OPTIONS请求。它用于向服务器请求权限信息,以确定实际请求是否安全。

  • option预检:是否能发出请求(浏览器主动发起预检请求,跟后端没有关系)

  • get,post是简单请求不需要预检(复杂请求才会预检),发预检请求的都是options

  • 预检是有时间效的,这一次预检在多久时间内的会有效,浏览器会根据失效时间来判断这次还需不需要预检

2023.7.13-人力资源后台管理系统_第35张图片

  • 预检请求是一个OPTIONS请求
  • 服务器收到预检请求后,会检查请求头中的Origin、Access-Control-Request-Method和Access-Control-Request-Headers字段,然后根据这些信息来判断是否允许实际请求。
  • 服务器通过响应头中的Access-Control-Allow-Origin、Access-Control-Allow-Methods和Access-Control-Allow-Headers字段来告诉浏览器是否允许跨域请求。
  • 预检请求的目的是为了在实际请求被发送之前,确保服务器会对跨域请求做出适当的响应。这样可以防止恶意网站对其他网站进行跨域攻击,保护用户和服务器的安全。
  • 预检请求是CORS机制的一部分,用于实现跨域资源共享。
  • 跨域是浏览器行为,没有浏览器就不会发生跨域
当服务器允许跨域请求时,在响应头中会包含以下字段和值:
  1. Access-Control-Allow-Origin: 指定允许访问该资源的源站。可以是具体的域名,也可以是通配符"*",表示允许任意域名的访问。

  2. Access-Control-Allow-Methods: 指定允许的HTTP方法。例如,GET、POST、PUT等。这个字段通常是一个逗号分隔的字符串,列出允许的方法。

  3. Access-Control-Allow-Headers: 指定允许的自定义请求头字段。这个字段通常是一个逗号分隔的字符串,列出允许的自定义请求头。

  4. Access-Control-Allow-Credentials: 指定是否允许发送跨域请求时携带cookie等凭据。它的值可以是true或false。

  5. Access-Control-Max-Age: 指定预检请求的有效期,单位为秒。在有效期内,可以复用之前的预检结果,在浏览器不再发起预检请求。

这些字段和值告诉浏览器允许指定的源站、HTTP方法、自定义请求头和凭据进行跨域请求。浏览器在收到这些响应头后,会判断是否符合跨域规则,并决定是否允许实际请求的发送。这种方式通过限制允许跨域请求的源站、方法和请求头的方式,确保跨域请求的安全性。

服务器和服务器之间会不会受跨域影响?为什么?

服务器和服务器之间不会受跨域影响。

  • 跨域请求的概念是指在浏览器中,由JavaScript发起的跨源(不同源的)HTTP请求。
  • 跨域请求受到同源策略(Same Origin Policy)的限制,它是一种浏览器安全机制,用于保护用户数据和减少安全风险。
  • 然而,当服务器与服务器之间进行通信时,而不是通过浏览器作为中介,跨域问题就不存在了。
  • 跨域问题主要针对浏览器环境中的跨源请求,用于保护用户的隐私和安全。
解决开发时的跨域

2023.7.13-人力资源后台管理系统_第36张图片

  • 所有发往/api的请求(包含/api的请求)==>全部转发到target指定的地址中去
  • http://localhost:9528/api/sys/login==>https://heimahritheimanet/api/sys/login
    2023.7.13-人力资源后台管理系统_第37张图片
    2023.7.13-人力资源后台管理系统_第38张图片

day2

复习
  1. 请求拦截器: 请求发出去之前最后一次加工 (token注入)
  2. 响应拦截器 :在发送请求后,接收到服务器返回的响应之前,对响应进行拦截和处理的功能。
  • 在人资项目中,错误的统一处理,就是给用户提示错误信息
  1. 浏览器如何知道某条资源的是什么类型的?
  • 响应报文Response Headers里面包含Content-Type
  • 服务器返回来的Content-Type
    2023.7.13-人力资源后台管理系统_第39张图片
axios

2023.7.13-人力资源后台管理系统_第40张图片
2023.7.13-人力资源后台管理系统_第41张图片

2023.7.13-人力资源后台管理系统_第42张图片

  1. 看请求==> 点开network , headers,preview,payload都要看
  • get请求没有payload,放在URL中
  • 其他请求放在body中
    在这里插入图片描述
  1. status=200段,不代表接口的调用逻辑(登录业务)一定是成功的,有可能用户名是错误
  2. status不是200段,代表接口的调用逻辑(登录业务)一定是失败的
//utils/request.js
// 响应拦截器
// 在人资项目中,错误的统一处理,就是给用户提示错误信息
service.interceptors.response.use((response) => {
  // 请求成功的回调:http的状态码就位2XX
  const { data, message, success } = response.data // 默认json格式
  if (success) {
    // 调用成功,业务也成功
    return data
  }
  // 调用成功,业务失败
  this.$Message({ type: 'error', message })
  return Promise.reject(new Error(message))
}, async(error) => {
  // http状态码不为200段的情况
  // error.message
  this.$Message({ type: 'error', message: error.message })
  return Promise.reject(error)
})

区分环境
  1. 开发环境
  • .env.development中设置开发环境变量默认 NODE_ENV 值为development
    在这里插入图片描述
  1. 生产环境
  • .env.production中设置生产环境变量默认 NODE_ENV 值为 production
    在这里插入图片描述
    2023.7.13-人力资源后台管理系统_第43张图片
  • 使用process.env.属性的方式获取
  • 自定义环境变量:必须以VUE_APP_开头
  1. 打包命令 npm run build:prod
    2023.7.13-人力资源后台管理系统_第44张图片
    npm run dev / npm run serve=>开发环境
    npm run build / npm run build:prod=>生产环境

  2. 在开发环境,填入用户名,生产环境为空
    2023.7.13-人力资源后台管理系统_第45张图片

  3. 主页权限验证
    2023.7.13-人力资源后台管理系统_第46张图片

登录流程
  • 登录按钮
  • 表单校验
  • 调接口,拿token(异步修改state中的数据=>actions中实现=>必有mutations),跳转页面

获取用户资料在Vuex中共享

登录之后获取当前用户的资料
获取的用户资料在Vuex中共享
2023.7.13-人力资源后台管理系统_第47张图片

  • 函数名使用小驼峰命名

获取资料action的调用位置
有token的位置再获取资料

charAt表示选择第几个字符

2023.7.13-人力资源后台管理系统_第48张图片

修饰符
  1. trim=>去掉空格
  2. native:原生
  3. 自定义事件不支持原生事件,加上.native就支持原生事件了
<el-dropdown-item divided @click.native="logout">
            <span style="display:block;">登 出</span>
</el-dropdown-item>

处理token过期

失效的token调接口=>401

补充

2023.7.13-人力资源后台管理系统_第49张图片

2023.7.13-人力资源后台管理系统_第50张图片

  1. 结论1: 定义在data中的数据,才是响应式数据
  2. 结论2: 动态添加到响应式对象上的新属性,不是响应式
  3. 结论3:要想让态添加的属性也是响应式的话,需要使用$set 方法

2023.7.13-人力资源后台管理系统_第51张图片

  • 在页面初始化的过程中,通常会有一个生命周期钩子函数或方法,比如created被调用的时刻就是在组件实例被创建后,但是在DOM渲染之前。

  • 如果在created钩子函数中没有进行相关数据的初始化或数据绑定操作,那么在此之前页面是没有内容显示的,因为此时页面的渲染还没有开始

0714作业:回答下面的问题:
  1. 重点:动态添加到组件上的数据为什么不能实现视图更新?
  • 因为不是绑定在data上的,只有绑定在data上的数据才是响应式数据
  • 动态添加在响应式对象上的新属性,不是响应式的
  1. 重点:动态添加到组件数据对象上的新属性,是不是响应式?
  • 不是
  1. 重点:如果要给组件的数据对象上添加一个具有响应式能力的新属性,应该怎么办?
  • 需要使用$set 方法
  1. 重点:登出逻辑是什么?精髓一句话
  • 从哪来,回哪去,怎么来的,怎样回去
  • 清除用户的身份认证信息和相关状态,使其无法再访问需要登录才能进行的操作或页面。
  1. 重点:获取用户资料最合理的时机是什么时候?
  • 登录之后,跳转到首页之前
  1. 重点:环境变量起到什么作用,如何读取环境变量的值,如何判断当前所处的环境?
  • 环境变量可以用于存储不同环境下的配置信息
  • 可以通过环境变量来区分程序运行在开发环境或生产环境中
  • .env.development中设置开发环境变量默认 NODE_ENV 值为development
  • .env.production中设置生产环境变量默认 NODE_ENV 值为 production
  • 可以使用 process.env 来访问环境变量
  1. 重点:如何自定义环境变量?举一个自定义环境变量应用的例子;
  • 自定义环境变量:必须以VUE_APP_开头
VUE_APP_BASE_API = '/dev-api'
VUE_APP_VERSION = '1.0.3'

VUE_APP_MOBILE= '13800000002'
VUE_APP_PASSWORD = 'hm#qd@23!'
  1. 重点:如何解决跨域问题(开发环境跨域)?
  • proxy
  • 所有发往/api的请求(包含/api的请求)==>全部转发到target指定的地址中去
  1. 重点:什么是同源策略?web中的哪些操作会受到同源策略的影响?
  • 两个页面地址的协议,域名,端口号一直就是同源,否则就是跨域
  • 当web页面使用多个元素或者打开其他浏览器窗口的时候,这一策略就会起作用

day3

修饰符
  1. .prevent阻止默认行为
    一般用于原生HTML标签
    @click.prevent="updatePassworda标签的默认跳转
  2. .native 表示给vue的自定义组件添加原生事件
  3. .sync支持子组件修改父组件的值
修改密码的弹框
  1. 绑定数据
  2. 绑定规则
    给绑定规则:
  • 1.定义规则
  • 2.给 el-form 绑定 :model 和 :rules
  • 3.给 el-form-item 设置 prop

封装组件

封装组件本质做什么
  1. 封装组件的目的 :是为了抽离独立的功能
  2. 封装组件,本质上可以理解为封装函数
封装函数的时候,要确认什么
  1. 函数是干啥用的
  • 组件的功能
  1. 函数名
  • 组件名
  1. 入参
  • 自定义属性=>props
  1. 出参
  • 函数的返回值=>给到父组件(父组件接受子组件的值=>子组件给父组件传值)=>自定义事件=>$emit
图片加载失败=>触发 οnerrοr=" "
  1. 图片加载成功=>触发 οnlοad=" "
  2. 图片加载失败=>触发 οnerrοr=" "
  • 如何知道img图片加载失败
  • 给img绑定一个事件@error=“onLoadError”
抽离组件的报错

2023.7.13-人力资源后台管理系统_第52张图片
不能直接在子组件中修改父组件中的值
.sync支持子组件修改父组件的值

抽离组件=>3种方法

2023.7.13-人力资源后台管理系统_第53张图片

修改密码组件优化,使用.sync简化双向数据传递

.sync语法糖原理

  • .sync在vue3中原理就是 :属性+@update属性
  • v-model原理就是 :value +@input(属性绑定+自定义事件)
完成修改密码组件抽离,使用props和自定义事件实现组件的显示和隐藏
  1. 第一种写法抽离组件
    2023.7.13-人力资源后台管理系统_第54张图片
//父组件Navbar.vue
    <ChangePassword :show-dialog="showPassDialog" @updateShowDialog="updatePassDialog" />

//子组件ChangePassword/index.vue
  <el-dialog width="500px" title="修改密码" :visible="showDialog" :modal-append-to-body="false" @close="onDialogClose">

2023.7.13-人力资源后台管理系统_第55张图片
2023.7.13-人力资源后台管理系统_第56张图片

子组件的el-dialog弹框显示与隐藏受visible的控制,visible的true/false被showDialog控制着,showDialog的开关与否,在父组件中是被showPassDialog把控

  • 在父组件中定义了一个函数updatePassword定义了showPassDialog的true,控制他的开启=>进而影响showDialog的开启=>el-dialog会开启弹框
  • updateShowDialog是由子组件传给父组件的自定义事件,由父组件自行修改,子组件同时传入false值控制弹框的关闭, 将false传给showPassDialog控制其变为false,进而关闭el-dialog的弹窗
修改密码组件优化,使用.sync简化双向数据传递
  1. 第二种写法抽离组件
    2023.7.13-人力资源后台管理系统_第57张图片2023.7.13-人力资源后台管理系统_第58张图片
//完整写法
//修改密码的弹框
<ChangePassword :show-dialog="showPassDialog" @update:showDialog="showPassDialog = $event " />
  • .sync 语法糖的作用: 简化对数据的双向操作,允许子组件触发固定形式的自定义事件,来修改父组件的值
  • 固定形式的自定义事件: update:属性名 (来源于 props)
// .sync简化写法
//修改密码的弹框
<ChangePassword :show-dialog.sync="showPassDialog" />
优化修改密码组件,使用$ref+ref .open方案实现弹框打开和隐藏
  1. this.$refs.ref.open()
  • 在子组件定义一个open方法
  • 在父组件调用$ref+ref .open
 <ChangePassword ref="passDialog" />
   openPassDialog() {
      // 能够打开修改密码的弹框即可
      // 只要能调到 open(),弹框就可以打开
      // 如何调用到 子组件 的方法??
      // $refs + ref
      this.$refs.passDialog.open()
    }

day4

动态规划
贪心算法
cookie

清理组件和路由
  1. 导入文件
    2023.7.13-人力资源后台管理系统_第59张图片
  2. 删除文件
    2023.7.13-人力资源后台管理系统_第60张图片
创建项目所需要的组件和路由
  ├── approval            # 审批管理
  ├── attendance          # 考勤管理
  ├── department          # 组织架构
  ├── employee            # 员工管理
  ├── permission          # 权限管理
  ├── role                # 角色管理
  ├── salary              # 工资管理
  ├── social              # 社保管理

//router/index.js
// 引入其他路由
import approval from './modules/approval'
import attendance from './modules/attendance'
import department from './modules/department'
import employee from './modules/employee'
import permission from './modules/permission'
import role from './modules/role'
import salary from './modules/salary'
import social from './modules/social'

export const constantRoutes = [
				  approval,
				  attendance,
				  department,
				  employee,
				  permission,
				  role,
				  salary,
				  social,
 			 ]

2023.7.13-人力资源后台管理系统_第61张图片

改变左侧菜单的图标和文字&& 在左侧sidebar菜单下显示与否

2023.7.13-人力资源后台管理系统_第62张图片

组织架构

树形结构

2023.7.13-人力资源后台管理系统_第63张图片

  1. element-ui提供了树组件el-tree
  2. 属性
  • data(绑定数据)
  • props (设置属性)
    • children(设置子节点的字段名)
    • label(设置显示内容的字段名)
  • default-expand-all (默认展开所有节点)

2023.7.13-人力资源后台管理系统_第64张图片

<template>
  <div class="container">
    <div class="app-container">
      <!-- 组织架构的属性组件 -->
      <el-tree default-expand-all :data="data" :props="defaultProps" @node-click="handleNodeClick" />
    </div>
  </div>
</template>
<script>
export default {
  name: 'Department',
  data() {
    return {
      data: [
        {
          username: 'hello',
          kids: [
            {
              username: '1.1'
            }
          ]

        },
        {
          username: 'world',
          kids: [
            {
              username: '2.1'
            },
            {
              username: '3.1',
              kids: [
                {
                  username: '3.1.1'
                },
                {
                  username: '3.1.2'
                }
              ]
            }

          ]
        }
      ],
      defaultProps: {
        children: 'kids',
        label: 'username'
      }
    }
  },
  methods: {
    handleNodeClick(data) {
      console.log(data)
    }
  }
}
</script>

2023.7.13-人力资源后台管理系统_第65张图片

获取组织架构数据 — 平面结构
  1. 用真实数据渲染=>获取接口

  2. 定义接口=>api文件夹

2023.7.13-人力资源后台管理系统_第66张图片

组织架构 — 递归转化树形结构

怎么写递归

  1. 递归本质是一种循环,所以写递归,一定要先找到循环体
  • 循环是广度遍历
  • 递归是深度遍历
  1. 递归一定要有开始条件或者要有结束条件
递归 — 爬楼梯问题(一维动态规划)
  1. 有一个N个台阶的楼梯, 每一步只能爬 1阶 或 2阶,问爬到楼梯的顶部有多少种爬法
  • 假设N=3 =>3种 111,12,21

  • 假设N=4 =>5种 1111,112,121,211,22

  • 假设N=10 => 89种

  • 从第四层到第五层=>1种

  • 从第三层到第五层=>2种

  • 斐波那契数列

  • 1=>1种

  • 2=>2种

  • 3=>3种

  • 4=>5种

  • 5=>8种

  • 6=>13种

function fibo(N) {
	if(N === 1) return 1
	if(N === 2) return 2
	return	fibo(N-1)+fibo(N-2)
	}
	console.log(fibo(5))//8种
	console.log(fibo(10))//89种

组织架构-添加子部门-新建弹层组件

2023.7.13-人力资源后台管理系统_第67张图片

补充

空对象和空数组转成if判断的时候都是true

2023.7.13-人力资源后台管理系统_第68张图片

逻辑运算!!(非非) / 双重否定
  1. “!” 是一个逻辑非运算符,它用于取反一个布尔值。“!!” 则是对该逻辑非的再次运算,相当于两次取反。
  2. 使用 “!!” 运算符的主要目的是将一个值转换为对应的布尔值。具体规则如下:
  • 如果操作数是一个真值(例如非零数、非空字符串、非空对象),“!!” 运算符将返回 true。

  • 如果操作数是一个假值(例如零、空字符串、null、undefined 或者 false),“!!” 运算符将返回 false。

  1. 逻辑值 !!1 对上一次的逻辑值 !1 取反
    !(!1) true
    2023.7.13-人力资源后台管理系统_第69张图片

空字符串false转成逻辑值也是false
2023.7.13-人力资源后台管理系统_第70张图片

var value1 = 0;
var value2 = "Hello";
var value3 = null;

console.log(!!value1); // false
console.log(!!value2); // true
console.log(!!value3); // false

双重否定运算符 “!!” 并不改变操作数本身的值,它只是返回一个相应的布尔值。

补充面试题
  1. 判断p是不是某个的实例
  • p instanceof Person
    2023.7.13-人力资源后台管理系统_第71张图片
    2023.7.13-人力资源后台管理系统_第72张图片
  1. 构造函数能不能不new直接调用
  • 可以,但大部分都是undefined
  • 构造函数没有返回值,相当于返回了undefined
  • 函数调完有结果=>一定有返回值=>return123
    2023.7.13-人力资源后台管理系统_第73张图片
    为什么(普通函数调用)直接返回和直接调用(构造函数new)的返回值不同
  • 如果 return 的是引用数据类型,比如 数组,对象的话,new 的结果就是 return 的结果;
  • 如果 return 的是非引用类型,比如 number,boolean的话,new 的结果不受影响;=>则打印是实例对象
    2023.7.13-人力资源后台管理系统_第74张图片
    new Boolean(false)转为布尔值=>true
    !!new Boolean(false)=true
    对数据进行布尔转换的时候,不能使用new Boolean转换=>因为new的结果都是实例对象=>永远是true
    2023.7.13-人力资源后台管理系统_第75张图片

2023.7.13-人力资源后台管理系统_第76张图片
如果想得到某个内置包装类型的值, 使用实例对象的一个方法 .valueOf()=>取值
2023.7.13-人力资源后台管理系统_第77张图片

  1. 单独调用构造函数,判断this指向
  • this指向window
  1. 单独调用普通函数,this指向是,谁调用指向谁,直接调用指向window
  2. 构造函数可以单独调用,function可以当构造函数使用,内部不一定有this,语法没有问题,但实际没有意义
  3. 构造函数一般没有return ,写了return的话,new完构造函数会返回什么===>
    2023.7.13-人力资源后台管理系统_第78张图片
    1. 构造函数如果有返回值,return,new 的结果会受到 return 的影响
  • 2.如果 return 的是引用数据类型,比如 数组,对象的话,new 的结果就是 return 的结果;
  • 3.如果 return 的是非引用类型,比如 number,boolean的话,new 的结果不受影响;=>则打印是实例对象Person{name:‘hello’}
  1. 内置包装类型:Number,Boolean,String
  • tostring(n) 表示把 前面的数字,转成 n 进制的字符串
  • 当我们把一个普通的值, 当做对象去调用时, JS内部的机制会帮我们把这个值包装成一个对应类型的实例对象
const num = 123;
console.log(num.tostring(2)) // tostring(n) 表示把 前面的数组,转成 n 进制的字符串
'abc'.includes('c') // true
// 以上 123 和'abc'都是简单的值,值不是对象,但是却可以当成对象去使用。为什么?
// 因为有内部的包装类型
// num ==> Number(123) ==> new Number(123)
const num2 = new Number(123)
console.log(num2.tostring(2)) // 二进制的字符串
//当我们把一个普通的值, 当做对象去调用时,  JS内部的机制会帮我们把这个值包装成一个对应类型的实例对象,new了一把,进而可以调用includes方法
  1. 构造函数是Function的实例对象
    2023.7.13-人力资源后台管理系统_第79张图片
 Number instanceof Function //true
 Number.tostring === Function.prototype.tostring//true
 Number.prototype.tostring === (123).tostring//true

 Number.toString === Function.prototype.toString//true
 Number.tostring === string.tostring//true

day5

函数式编程:把函数作为入参或者出参来
2023.7.13-人力资源后台管理系统_第80张图片
git stash 暂存
git stash pop把暂存文件拿回来

错误

代码: 表单规则已定义,表单数据和规则已绑定,但是表单校验不起作用;
原因:绑定的属性 :model 拼错了,写成了 :mode
结论:下次表单校验不生效要首先查三个属性有没有写对,:model :rules prop

day6

想要获取什么参数,可以通过传进一个箭头函数,在函数内部中调用传过来的箭头函数来读取其值 => 函数式编程

设计模式

生成校验函数

高阶函数: 一个函数调用之后,返回之后是另一个函数
2023.7.13-人力资源后台管理系统_第81张图片

 // 高阶函数(2阶)
    function createValidator(key) {
    //闭包
      const fun = async(rule, value, callback) => {
        const list = await getDepartmentList()
        const fn = this.isEdit ? item => item.id !== this.formData.id : () => true
        const isExist = list.filter(fn).some(item => item[key] === value)
        isExist ? callback(new Error('部门中已经有该名称了')) : callback()
      return fun
    }
  }
  
export default{
	data(){
		return{
		 rules: {
        name: [
          { required: true, message: '部门名称不能为空', trigger: 'blur' },
          {
            min: 2, max: 10, message: '部门名称的长度为2-10个字符', trigger: 'blur'
          },
          {
            trigger: 'blur',
            // 自定义校验模式
            validator: createValidator('name', this, '名称')
          }
        ], // 部门名称
        code: [
          { required: true, message: '部门编码不能为空', trigger: 'blur' },
          {
            min: 2, max: 10, message: '部门编码的长度为2-10个字符', trigger: 'blur'
          },
          {
            trigger: 'blur',
            validator: createValidator('code', this, '编码')
          }
        ], // 部门编码
		}	
}
}

闭包=>技术点
高阶函数=>设计函数
闭包: 一个函数执行一下,返回另一个函数

设计模式 =>对缓存进行=>包装器

2023.7.13-人力资源后台管理系统_第82张图片
设计方案=>闭包=>包装器
进阶思考 4:上面校验唯一性的时候,每次都会重新调接口,有点浪费
现在需要对获取部门列表的接口做数据缓存,缓存时间2小时
也就是说,如果两小时内重复调用获取部门列表的接口,就返回之前缓存的数据
如果超过2小时,再重新调接口获取新数据
2023.7.13-人力资源后台管理系统_第83张图片
2023.7.13-人力资源后台管理系统_第84张图片
2023.7.13-人力资源后台管理系统_第85张图片

2023.7.13-人力资源后台管理系统_第86张图片
2023.7.13-人力资源后台管理系统_第87张图片
2023.7.13-人力资源后台管理系统_第88张图片

手写一个防抖函数

对传入的fn进行防抖处理,支持传入时间

一段时间内点击多次,只执行最后一次

function debounce(fn,time){
//定义一个防抖函数
 let timer=null
 //初始化定时器为空
 return function (){
 //返回一个匿名函数作为闭包
	 if(timer !== null ){
	 //如果定时器不为空
		 clearTimerout(timer)
		 //如果定时器存在,则清除之前的定时器
 }
	timer=setTimeout(fn,time)
	//设置一个新的定时器,延迟time执行传入的函数fn
	
	}
}
debounce(createValidator)()
判断是否为质数 => 暴力枚举法

牛课题

const arr=[]
function zhiyinizi(num){
	for (let i = 2 ; i <= num ; i++){
		if( num % 2 === 0) {
			arr.push(i) //2 2 3 3 5
			zhiyinzi(num / i)
			return 
		}
	}
}
zhiyinzi(180)
console.log(arr)  //{2,2,3,3,5}

角色管理

role/index.vue
2023.7.13-人力资源后台管理系统_第89张图片

行内编辑
  1. 如何知道点击的是当前行=>插槽 v-solt
  2. 条件渲染 => 添加的数据必须为响应式
  3. 为何数据变了,视图没更新
  • 直接添加的新属性不是响应式,所以没有触发视图更新
  • this.$set(row,'isEdit',false) 这种是响应式的
    2023.7.13-人力资源后台管理系统_第90张图片
  1. 发数据报错
    查看=>地址,类型,字段名,字段值
  2. 将true/false => 1/0在这里插入图片描述
  3. row.editRow = { ...row } 是将名为 row 的对象进行浅拷贝,并将拷贝后的对象赋值给 row.editRow。
  • { …row } 使用了展开语法 ,它将对象 row 中的所有属性和值都展开为一个新的对象。
  • 这个新的对象与原始对象 row 是浅拷贝关系,即新对象中的属性值是原始对象中的引用。
  • 所以,row.editRow 将引用一个与 row 相同的对象,但是它是一个新的对象,对 row.editRow 的修改不会影响到 row 对象本身。
  • 这在一些场景中常用于备份原始数据,以便在编辑过程中进行对比或回滚。
  1. 编辑修改后取消,再点编辑是修改后的数据 => 修改复制数据的拷贝的时机 => 保留状态
  • 点编辑之前复制 => 非保留状态,每次都是修改取消前的数据

补充 => 位运算

  1. 进制
    每个数字所占的位,表示的是有几个N

  2. 八进制
    10215 => 2表示2个 (8个8)

  3. 十六进制
    0x343455

  4. 二进制
    b101001010
    2^0 +
    2^1 +
    2^2 +
    +…2^9

  5. 字节+比特位
    18yte = 8bit
    18=8b

  • 1字节最多能存放256

  • 每个比特位有两种情况 , 一个字节最多有256种情况 ,最大能表示得数是255
    =>1字节最多存放256
    2023.7.13-人力资源后台管理系统_第91张图片
    8位通道色 1600万色

  • 在JS里面,一般使用8个字节来存放一个数字 2^64

  • 32转为二进制 console.log(num.toString(2)) // 00100000

  1. 左移运算符 <<
  • 双元运算符 => 左右都必须有值
  • console.log(32 << 1) // 64
  • 00100000 => 01000000
  • console.log(32 << 2) // 128
  • console.log(128 << 1) // 256
  1. 右移运算符
  • console.log(32 >>1) //16
  • console.log(32 >> 2) // 8
  • console.log(32 >> 3) // 4
  • console.log(32 >> 32) // 0
  1. 按位与 & (位运算的时候 低位要对齐)
    00100000 => 32
    00010000 => 16
    ----------------------- &(第一位对齐)
    00000000 => 0 (都为1才为1)
  • 运算逻辑: 每一位进行比较 ,从低位开始逐位比较 , 都为1 ,结果为1, 否则为0
  1. 按位或 | (位运算的时候 低位要对齐)
  • 运算逻辑:每一位进行比较,从低位开始逐位比较,有一个为 1 ,结果就位 1,都为 结果才为
    100000
    010000

110000 => 48

  1. 按位异或
  2. 按位取反

day7

员工

  1. 自定义列表的项=>插槽
    1. 在 Vue 组件中,以下哪个对数组的操作可以触发视图更新?
      A. sort()
      B. split()
      C. indexOf()
      D. replace()
  • 触发视图=>数据改变=>哪个数组可以改变数据=> sort()
场景兼容

组件复用要考虑场景兼容,使用v-if条件判断

设置高亮

2023.7.13-人力资源后台管理系统_第92张图片

  1. 这里需要给定node-key属性,否则setCurrentKey方法不知道设置的是哪个字段的值
  • setCurrentKey方法是给node-key绑定监听id属性名所对应的属性值,即departmentId
 <el-tree
          ref="deptTree"
          node-key="id"
          :data="depts"
          :props="defaultProps"
          default-expand-all
          :expand-on-click-node="false"
          highlight-current
          @current-change="selectNode"
  />
  1. 补充:为什么使用 n e x t T i c k ,因为我们设置完树形之后立刻选中首个节点,此时更新还没有完成,必须等待更新完成后,再去选中首个节点,所以需要使用 nextTick,因为我们设置完树形之后立刻选中首个节点,此时更新还没有完成,必须等待更新完成后,再去选中首个节点,所以需要使用 nextTick,因为我们设置完树形之后立刻选中首个节点,此时更新还没有完成,必须等待更新完成后,再去选中首个节点,所以需要使用nextTick
深度监听
  1. 监听对象中的属性,可以使用key:value键值对的写法(不需要深度监听)
  • 使用 watch 侦听器坚监听keyword 的变化,因为是复杂数据类型,所以要进行深度监听,也可以直接写成"queryParamskeyword " : function(){this.onKeywordChange}
  1. 监听深度变化的时候,不能使用箭头函数
  • 因为箭头函数绑定了当前上下文的作用域,会导致监听函数内部的this指向发生变化,从而无法正确地访问到Vue实例的属性或方法。
  • 只能使用具名函数或者function函数
  • 通常会使用watch选项来监听对象的深度变化。在watch选项中,可以通过指定一个普通函数作为监听函数,这样就能确保函数内部的this指向是正确的。
    2023.7.13-人力资源后台管理系统_第93张图片
属性组件=>组件的递归调用
  1. 组件自己调自己=> 组件递归

2023.7.13-人力资源后台管理系统_第94张图片

  1. 数据有子节点,组件就有子节点
  2. 不管是methods和created都不能使用箭头函数,箭头函数没有自己的this指向

补充 位运算符的使用 左移(十进制转二进制)得到二进制数的高位(第二个8位数)和低位(第一个八位数)

二进制转十进制

有一个数 num = 19,num 的有效字节为 2 个,分别为 3 和 232
1000 => 900311 1111969
解释:1000 的8个字节中,只有低位的2个字节有值,这两个字节分别为 3 和 232求 12,234 表示的数是多少?
12 => 00001109
234 ==> 11101010

  • 思路1=>算法一:先把这两个数分别转为二进制,并补到8 位
  • 二进制转十进制parseInt(110011101010,2)//3306
  1. 例1
    求 12,234 表示的数是多少?
  • 算法一
//求 12,234 表示的数是多少?
//十进制转位二进制
(1000).toString(2)//'1111101000'
(12).toString(2)//'1100'
(234).toString(2)//'11101010'
//将12和234的二进制数(补齐8位)拼接起来=>转为十进制
parseInt('0000110011101010',2)//3306
  • 算法二
    求 12,234 表示的数是多少?
    将12左移8位 ,与234=>3306
12<<8|234 //3306
  1. 例2
//求 121,9,201 表示的数是多少?
(121).toString(2)//'1111001'=>'01111001'
(9).toString(2)//'1001'=>'00001001'
(201).toString(2)//'11001001'
//将121,9,201的二进制(补齐8位)拼接起来,再转为十进制
parseInt('011110010000100111001001',2)//7932361
  • 算法二 使用左移运算符
    求 121,9,201 表示的数是多少?
121<<16|9<<8|201//7932361

任何数和255与完都是那个数
1000 & 0xff =>1000
1000 & 255 =>1000
任何数与0都是0
在这里插入图片描述
2023.7.13-人力资源后台管理系统_第95张图片

1000&255 //232
1000>>8 &255 //3

day8

Response Headers
  1. 浏览器如何知道请求发送出去之后返回的是JSON格式 ?
  • 浏览器通常根据服务器响应的Content-Type标头来确定返回的数据格式。
    2023.7.13-人力资源后台管理系统_第96张图片
  • 只有JSON才能直接解构
    2023.7.13-人力资源后台管理系统_第97张图片

2进制文件流

  1. .hex 16进制文件
  2. .bin 2进制文件

2023.7.13-人力资源后台管理系统_第98张图片
2023.7.13-人力资源后台管理系统_第99张图片
3. 可以将2进制文件转为blob对象,比较好处理(2进制文件流很难处理)
4. 怎样转

  • 通过配置项: 告诉axios对请求返回的数据,自动转成blob格式
// 导出Excel
export function exportEmployeeExcel() {
  //  通过配置项: 告诉axios将下面的请求返回数组,处理成blob类型
  // 处理成blob的目的- 方便后续通过js代码处理文件
  // 当前场景,是服务器会返回二进制文件流 ==> 遇到二进制文件流可以使用 blob 格式来处理
  // 其他场景:返回图片,返回文件 ===> blob
  request.request.get('/sys/user/export', { responseType: 'blob' })
}

在这里插入图片描述

  1. 处理成blob的目的
  • 方便后续通过js代码处理文件
  1. 当前场景,是服务器会返回二进制文件流 ==> 遇到二进制文件流可以使用 blob 格式来处理
  2. 其他场景:返回图片,返回文件 ===> blob
  3. 哪个接口需要转,就单独配置哪个接口,没有配置的接口不受影响
  4. 目的是 点击导出按钮,将文件下载到本地
  • 1.二进制文件流不方便直接下载,所以需要转 blob
  • 2.拿到 blob 格式以后,就可以通过某种方法 (s方法) 来实现下载
3.todo: 百度一下,如何将一个 blob 数据已文件的形式下载到本地?

blob下载思路:

  1. Vue axios使用Blob下载二进制流文件(get 传参)

2023.7.13-人力资源后台管理系统_第100张图片

 exportExcel() {
      exportEmployeeExcel()
        .then(res => {
          console.log(res)
          const blob = new Blob([res], {
            type: 'application/vnd.ms-excel'
          }) // 为blob设置文件类型,这里以.xlsx为例
          const url = window.URL.createObjectURL(blob) // 创建一个临时的url指向blob对象
          const a = document.createElement('a')
          a.href = url
          a.download = '人资员工信息表(使用a标签下载方法).xlsx'
          a.click()
          // 释放这个临时的对象url
          window.URL.revokeObjectURL(url)
        })
    }
  • 还可以封装为一个组件,方便 导入模板下载时 使用
// 导出Excel
export function exportEmployeeExcel() {
  // 通过配置项: 告诉axios将下面的请求返回数组,处理成blob类型
  // 处理成blob的目的- 方便后续通过js代码处理文件
  // 当前场景,是服务器会返回二进制文件流 ==> 遇到二进制文件流可以使用 blob 格式来处理
  // 其他场景:返回图片,返回文件 ===> blob
  return request.get('/sys/user/export', { responseType: 'blob' })
}
// 目的是 点击导出按钮,将文件下载到本地
// 1.二进制文件流不方便直接下载,所以需要转 blob
// 2.拿到 blob 格式以后,就可以通过某种方法(s方法) 来实现下载
// 3.todo: 百度一下,如何将一个 blob 数据已文件的形式下载到本地?



export function saveAs(blob, filename) {
  const url = window.URL.createObjectURL(blob) // 创建一个临时的url指向blob对象
  const a = document.createElement('a')
  a.href = url
  a.download = filename
  a.click()
  // 释放这个临时的对象url
  window.URL.revokeObjectURL(url)
}
import { saveAs } from '@/utils/index'
    async exportExcel() {
      const result = await exportEmployeeExcel()
      // 认为,我而要的结果(result)就应该是一个 Blob 对象
      console.log(result)
      // 想法办讲 blob 对象以文件的形式下载到本地?
      exportEmployeeExcel()
        .then(res => {
          console.log(res)
          const blob = new Blob([res], { type: 'application/vnd.ms-excel' })
          // 为blob设置文件类型,这里以.xlsx为例
          saveAs(blob, '人资员工信息表(使用a标签下载方法).xlsx')
        })
    }
  1. 安装file-saver包,实现下载Blob文件npm run file-saver
    2023.7.13-人力资源后台管理系统_第101张图片
// 导出Excel
export function exportEmployeeExcel() {
  // 通过配置项: 告诉axios将下面的请求返回数组,处理成blob类型
  // 处理成blob的目的- 方便后续通过js代码处理文件
  // 当前场景,是服务器会返回二进制文件流 ==> 遇到二进制文件流可以使用 blob 格式来处理
  // 其他场景:返回图片,返回文件 ===> blob
  return request.get('/sys/user/export', { responseType: 'blob' })
}
// 目的是 点击导出按钮,将文件下载到本地
// 1.二进制文件流不方便直接下载,所以需要转 blob
// 2.拿到 blob 格式以后,就可以通过某种方法(s方法) 来实现下载
// 3.todo: 百度一下,如何将一个 blob 数据已文件的形式下载到本地?

import FileSaver from 'file-saver'
async exportExcel() {
      const result = await exportEmployeeExcel()
      // 认为,我而要的结果(result)就应该是一个 Blob 对象
      console.log(result)
      // 想法办讲 blob 对象以文件的形式下载到本地?
      FileSaver.saveAs(result, '人资员工信息表.xlsx')
 }
员工管理-员工导入-上传excel
  1. form-data => 内置对象=>可以new一个
const formData = new FormData()
formData.append('file", file)
  1. change事件要触发,input的value必须要改变
  2. 需要对input文件域的值做一下清空操作文件域type="file"
    e.target.value=’ ’
  3. this.$refs.属性名 和 this.$refs[属性名] 等价
  4. 文件域样式很难改,一般隐藏掉
    2023.7.13-人力资源后台管理系统_第102张图片

day9

员工头像
  1. 对大小进行校验
    2023.7.13-人力资源后台管理系统_第103张图片

腾讯云

  1. 存储桶
    2023.7.13-人力资源后台管理系统_第104张图片
  2. 配置跨域
    2023.7.13-人力资源后台管理系统_第105张图片
  3. 存储桶
    2023.7.13-人力资源后台管理系统_第106张图片
  4. 密钥
    2023.7.13-人力资源后台管理系统_第107张图片
    AKIDKYZP4bw99wWvfHk18E9sPiroYBh4FC9v
    e4INI1X0MVP73ogP83mGZXMzOcx60iHx
使用步骤
  1. 执行命令 npm i cos-js-sdk-v5 --save安装 SDK 依赖

  2. 引入import COS from 'cos-js-sdk-v5';
    2023.7.13-人力资源后台管理系统_第108张图片
    2023.7.13-人力资源后台管理系统_第109张图片

  3. 前端使用固定密钥计算签名,该格式适用于前端调试,若使用此格式,请避免泄露密钥

const cos = new COS({
    SecretId: 'SECRETID',
    SecretKey: 'SECRETKEY',
});

2023.7.13-人力资源后台管理系统_第110张图片

  1. 上传对象
    2023.7.13-人力资源后台管理系统_第111张图片
    改参数
    uploadImg({ file }) {
      console.log(file)

      const cos = new COS({
        SecretId: 'AKIDKYZP4bw99wWvfHk18E9sPiroYBh4FC9v',
        SecretKey: 'e4INI1X0MVP73ogP83mGZXMzOcx60iHx'
      })
      cos.uploadFile({
        Bucket: 'hm-hr-20230724-1319629237', /* 填写自己的 bucket,必须字段 */
        Region: 'ap-nanjing', /* 存储桶所在地域,必须字段 */
        Key: 'file.name', /* 存储在桶里的对象键(例如:1.jpg,a/b/test.txt,图片.jpg)支持中文,必须字段 */
        Body: file, // 上传文件对象
        SliceSize: 1024 * 1024 * 5, /* 触发分块上传的阈值,超过5MB使用分块上传,小于5MB使用简单上传。可自行设置,非必须 */
        onProgress: function(progressData) {
          console.log(JSON.stringify(progressData))
        }// 上传进度
      }, function(err, data) {
        if (err) {
          console.log('上传失败', err)
        } else {
          console.log(data)
          console.log('上传成功')
          this.$emit('input', 'https://' + data.Location)
        }
      })
    }
  1. 上传成功
    在这里插入图片描述
    2023.7.13-人力资源后台管理系统_第112张图片

  2. 回显成功
    2023.7.13-人力资源后台管理系统_第113张图片

  3. 用完就删除桶, 避免产生流量费用
    2023.7.13-人力资源后台管理系统_第114张图片

面试题提问补充

v-model
  1. v-model="count" <=> :value="count" @input="count = $event"
  2. 只要组件内部支持 :value 和 @input 事件,外部调用组件时就可以使用
  3. 自定义组件也可以实现v-model指令,只要入参value,出参input就可以实现v-model
  4. v-model默认实现方案是 :value和@input 默认情况下,model 选项中的 prop 值为 value ,event 值为 input
  5. 可以使用 model 修改 v-model 的实现方案
model:{
	prop:'value',
	event:'input'
}
model:{
	prop:'value',
	event:'change'
}

2023.7.13-人力资源后台管理系统_第115张图片

day10

权限

  1. 权限点的操作
  • 访问权限:能否看到页面 => 路由
  • 按钮的操作权限:能否看见按钮或者能否点击
  1. 如何实现 按钮的操作权限
  • 按钮的条件渲染(能否看见按钮)
  • 按钮的disabled(能否点击)
  1. 人太多,分配权限太麻烦 => RBAC
  • 给角色分配权限 < 直接给员工分配权限(间接拥有权限)
  • 通过员工和角色的关系,一个员工不一定只有一个角色
  1. RBAC
  • 给用户分配角色,给角色分配权限
  1. 一级权限: 路由权限
  2. 二级权限: 按钮权限

简历

  1. 要:
  • 耐心
  • 毅力
  • 接受否定
简历
  1. 个人信息:姓名,性别,年龄,联系电话,学历,贴照片
  • 重点体现优势,靠前写=> 学历:本科
  • 不是优势的不写或者模糊写
  1. 技术栈的描述
  • 熟练掌挥媒体查询技术,能够实现响应式网页布局,掌握rem、vw/vh移动适配方案

  • 媒体查询

  • 熟练掌握ES6新特性例:let , const.模板字符串、箭头函数、解构赋值,promise等;

  • 熟练使用ajax和axios插件与后台进行数据交互;

  • 熟练使用elemnt-ui、vant等UI组件库快速的进行页面开发

  • 熟练使用Git进行版本控制,以及进行团队协作开发:

  • 熟练使用调试工具,能够快速解决编码问题

  • 了解webpack的基本配置和使用了解ECharts,能实现简单的数据可视化;

  • 有良好的代码风格和编程习惯。

  • 英文水平良好,可流畅阅读英文文档

  • 具有基本的英文阅读能力,善于翻阅资料,查询相关文档解决问题

  • 广度 深度

  • 不要写精通

  • 写一两个,不要太多了解 , 少写熟悉

  • 先写熟练 , 再写了解

  1. 就职经历
  • 倒序书写
  1. 项目经历
  • 倒序书写
  • 项目组成 : PC端+移动端+小程序端+大屏数据可视化
  • 技术找组成: Vue2 + Vue3 + TS + Sass/Less + Axios + Element-UI (其他UI框架)
  • 技术栈和项目的加分项 : websocket + WebWoker + 设计模式 + 基于Vue的低代码开发 + GIS + 3D地图
  • 不要出现OA 人资 小兔鲜 学成在线 品优购 黑马面经 优医问诊之类的字眼

day11

复习

闭包

一般形式: 一个函数调完返回另一个函数,内部函数使用外部函数的变量,可以延长作用域链

高阶函数
  1. 当一个函数调用完返回另一个函数,那个函数就叫高阶函数
  2. 作用:在 设计模式 可以做 包装器
ext.js

ext.js(又称为Sencha Ext JS)是一个JavaScript应用程序框架,用于构建跨平台的富客户端应用程序。
它提供了丰富的UI组件、数据管理和模块化开发工具,可以帮助开发者快速构建功能强大、交互性强的Web应用程序。

补充 : async => 并发请求 => 静态方法 => Promise.all

任何一个被async修饰的函数 , 都会变成异步函数 , 这个异步函数的返回值是一个promise

  1. await+函数=>函数只能是异步的
  2. await只发生在当前调用内有效(只发生在局部)
  3. 有 await 的地方,一定有 async ==> 近朱者赤
  • 一个函数的内部只要有异步调用,并且异步调用需要被 await 等待的话,这个函数就一定是异步函数,所以要加 async
  1. 有 async 的地方,不一定有 await
  2. 并发请求:同时向服务器发送请求 , 两条请求是并发的,请求总耗时是耗时长的那个请求(最大值)
  3. 能不能并发由业务决定,业务上没有先后顺序的接口,可以并发调用 ==>为了节省时间
  4. 获取请求是为了渲染页面 , 获取角色列表和获取用户拥有的角色在业务上没有先后关系 , 因为数据绑定的不同 , 所以可以并发请求
  5. 实现并发的方式:
  • 直接并列着写,不要 await就是并发
  • 用Promise.all
  1. Promise.all就是用来处理并发请求的(静态方法)
  2. 静态方法:挂载在构造函数上的方法
  • Array.isArray()
  • Object.keys()
  • Object.assign()
  • Object.values()
  • Object.define
  • Property()
  • Promise.all()
  1. Promise.all=> 静态方法
  • 调用之后 , 返回值是Promise对象(不能直接forEach[数组可以直接forEach])
  • .then之后的res才是数组
  • 入参 => Promise数组: 数组里面的每一项都是Promise对象
  1. 如何得到两个并发请求(如何写入参)
  • 直接调这俩函数 => Promise对象
  • Promise.all([this.getRoleList() , getUserInfo(id)]).then(res => {})
    2023.7.13-人力资源后台管理系统_第116张图片
  1. Promise.all的then方法中,拿到的结果 => 数组
    2023.7.13-人力资源后台管理系统_第117张图片

权限

路由权限 => 根据用户权限添加动态路由
  1. 根据用户权限分离静态路由和动态路由
    // 需要根据用户权限进行动态注册的路由表
  2. 登录之后 , 进入首页之前
  3. 细化 => 获取用户信息之后,跳转后台首页之前 => permission.js
  4. 静态路由+动态路由
  5. 将筛选出来的路由,动态注册。如何动态注册?
  • router 可以动态注册新的路由,addRoutes([动态注册的路由列表])
  • router.addRoutes(routes)
  1. menus字段中有角色对应的权限路由
  2. 解决 侧边栏同步更新
  • 将筛选出的动态路由,更新到 user 模块的 routes 中
  • store.commit('user/setRoutes',routes )
  1. 登出
  • 清空注册的路由信息
  • 删除token
  1. 重置路由
  • context.commit('setRoutes')
  • 调用已经写好的方法resetRouter()
按钮权限

实现按钮操作权限:条件渲染 / 自定义指令

  1. 按钮显示与否 v-if="points.includes('addUser')
  2. 自定义指令Vue.directive('自定义指令名,不带v-' , {自定义指令的配置项})
    2023.7.13-人力资源后台管理系统_第118张图片

补充

set和map是ES6新语法(可以去重)
Set
  1. Set 一种数据结构,存放不重复的数的集合
    -const set = new Set()
  2. 使用字面量创建的引用数据类型,引用地址是不一样的
  • 例1
    2023.7.13-人力资源后台管理系统_第119张图片
  • 例2
const set = new Set([1,1,2]) // 1,2
    set.add(1) // 1,2
    set.add('hello')
    set.add([1,2])
    set.add([1,2])
    // [] === [] ==> false 使用字面量创建的引用数据类型,引用地址是不一样的
    const arr = [1, 2]
    const list = arr
    set.add(arr)
    set.add(arr)
    set.add(list)
    console.log(set) //6条数据

2023.7.13-人力资源后台管理系统_第120张图片

  • 例3
    2023.7.13-人力资源后台管理系统_第121张图片
  1. 是否含有(true / false) console.log(set.has({}))

  2. 读长度console.log(set.size ) //7

  3. set.clear()清空

在这里插入图片描述

Map
  1. Map 一种数据结构,存放键值对,类似于 object,但 Map 对键的类型没有要求
  • const map = new Map()
  1. 删除delete obj.name

2023.7.13-人力资源后台管理系统_第122张图片

现有一个 Person 构造函数,有四个实例对象
// 现有一个 Person 构造函数,有四个实例对象
function Person(name) {
	this.name = name
}
const p1 = new Person('张三')
const p2 = new Person('李四')
const p3 = new Person('王五')
const p4 = new Person('老六')

map.set(p1,0)
map.set(p2,0)
map.set(p3,0)
map.set(p4,0)

map.set(p1, map.get(p1) + 1)

// 现在观众对 p1 ~ p4 四位选手进行投票,投票分 A B C D 四类,如果选手投了 A ,则 张三 得一分
// 以此类推,D 老六得一分
// 已知现在已经回收观众投票,投票结果为:
const res ='ABCDBCBSHCBSABCBSODHABDOAJDBSCDJABDCDBABDABCABDGSBCDHAHDWS'
// 请对上述结果进行统计,超出 A B  D 四类的票为无效投票,不计入
// 请分别计算出 p1 ~ p4 四位选手的得票数

// 两数之和
// 有一个数组,arr = [1,4,2,7,6,8,3,9]
// 给一个target =6
// 求数组中两数和等于 target 的元素的索引是多少
// 输出:[1,2]
// 假设 target = 10
// 求满足条件的第一个组合的索引是多少? [1,4]
 

day12

  1. 增加初始字段
    结论:遇到对对象进行连续访问的时候,就要考虑中间的某一次访问可能会得到undefined/null
    那么这个时候继续访问的话,就会报错:
    bug
    怎么解决:可以使用可选链操作符
    在模板数据中,可以使用初始字段
  2. vue中引入echarts
    1.在template中找到绘制图表的位置加上div标签
    2.给div加入ref属性
    3.什么时候渲染?渲染要等到获取数据之后
    4.根据需求去修改图表样式
  3. 当屏幕进行缩放的时候,echarts图表怎么自适应?chart.resize()
    窗口大小发生变化的时候,就调用chart.resize()方法
    在mounted/created中监听窗口大小的改变使用window.addEventLinstener('resize',()=>{调chart.resize()方法})
    总结:
  4. em是相对于自身字号的一个相对单位,自身字号如果不设置的话就去继承父元素的字号,就会变成相对于父元素的相对单位,如果自身设置了字号,就是相对于自己的相对单位
  5. 盒模型:
  6. 标准盒模型的宽度是内容的宽度,width属性只表示设置内容宽
  7. 怪异盒模型的宽度是内容+内边距+边框的宽度,width属性表示设置总宽
  8. 如何在打包项目的时候排除一些文件?
    1.在vue.config.js中的configureWebpack下配置externals来设置外部依赖以达到排除打包的目的
externals:{
	//项目中的包名(在package.json中找):外部包的包名(可以在百度上问CDN引入的element-ui叫什么 )
	//排除打包以后其实就是用外部的包名替换内部的包名
	'element-ui':'ELEMENT'
}

排除打包总结:减少项目体积,目的:为了让用户打开页面的速度更快,怎么实现:在vue.config.js的webpack的配置项中设置externals,最后在public文件下的index.html中引入样式文件和js文件
部署上线
2023.7.13-人力资源后台管理系统_第123张图片

你可能感兴趣的:(arcgis,vue)