资讯专栏INFORMATION COLUMN

前端常用的工具类函数, 持续更新中

wyk1184 / 592人阅读

摘要:在开发项目的时候,有一些场景用到次数频繁的函数,就封装在了自己的工具类里,在这里和大家分享一下通过获取到数据列表中对应显示的字段经常做平台类的项目,容易碰到这样的场景,增删改查页面,添加完之后,表格要显示某个类型,但是接口返回数据是类型,就

在开发项目的时候,有一些场景用到次数频繁的函数,就封装在了自己的工具类里,在这里和大家分享一下

1. 通过value获取到数据列表中对应显示的字段

经常做平台类的项目,容易碰到这样的场景,增删改查页面,添加完之后,表格要显示某个类型,但是接口返回数据是类型ID,就可以通过这个方法得到对应要显示的字段了。

 用法示例:let list = [{id: 1, name: "深圳"}, {id: 2, name: "广州"}]
          getDataName({dataList: arr, value: "id", label: "name", data: 1}) // 深圳
          getDataName({dataList: arr, value: "id", label: "name", data: 2}) // 广州

 /**
   * 通过value找到在列表中对应的名字
   * @param {Object} obj
   *  @param obj.dataList 数据列表
   *  @param obj.value    数据的值对应的字段名称   例如 "value"
   *  @param obj.label    数据的说明对应的字段名称 例如 "label"
   *  @param obj.data     当前传入的数据值
   * @return name        返回当前传入值在数组中对应的名字
   */
  getDataName: (obj) => {
    let name = obj.data
    if (Array.isArray(obj.dataList) && obj.dataList.length > 0) {
      for (let i = 0; i < obj.dataList.length; i++) {
        if (obj.dataList[i][obj.value] == obj.data) {
          name = obj.dataList[i][obj.label]
        }
      }
    }
    return name
  }
2. 对请求失败的HTTP状态码做处理

说多了都是泪,之前公司接口返回数据,一开始没有做异常处理,然后在使用的时候一旦出现什么问题页面上就是一大堆的英文,很长很长一串,或者是出现问题了不返回错误原因,然后说影响用户体验,但是后端又不做异常处理,于是就写了一个关于http状态码的处理。根据返回的状态码页面上显示对应的提示内容,不过感觉稍微正常的流程都用不上这个,哈哈

/**
   * 对请求失败的HTTP状态吗做处理
   * @param {Number} code     HTTP状态码
   * @param {String} message  错误提示
   * @return message 返回处理过的提示信息
   */
  requestError: (code, message) => {
    let statusCode = (code + "").replace(/[^0-9]+/g, "") - 0

    switch (statusCode) {
      case 400:
        return "Bad Request (错误的请求)"
      case 401:
        return "Unauthorized (请求要求身份验证)"
      case 403:
        return "Forbidden (服务器拒绝请求)"
      case 404:
        return "NOT Found (服务器找不到请求的资源)"
      case 405:
        return "Bad Request (禁用请求中指定的方法)"
      case 406:
        return "Not Acceptable (无法使用请求的内容特性响应请求的网页)"
      case 407:
        return "Proxy Authentication Required (需要代理授权)"
      case 408:
        return "Request Timed-Out (服务器等候请求时发生超时)"
      case 409:
        return "Conflict (服务器在完成请求时发生冲突。服务器必须在响应中包含有关冲突的信息)"
      case 410:
        return "Gone (请求的资源已被永久删除)"
      case 411:
        return "Length Required (服务器不接受不含有效内容长度标头字段的请求)"
      case 412:
        return "Precondition Failed (未满足前提条件)"
      case 413:
        return "Request Entity Too Large (请求实体过大)"
      case 414:
        return "Request, URI Too Large (请求的 URI 过长)"
      case 415:
        return "Unsupported Media Type (不支持的媒体类型)"
      case 429:
        return "您的操作过于频繁,请稍后重试"
      case 500:
        return "Internal Server Error (服务器内部错误)"
      case 501:
        return "Not Implemented (尚未实施)"
      case 502:
        return "Bad Gateway (错误网关)"
      case 503:
        return "Server Unavailable (服务不可用)"
      case 504:
        return "Gateway Timed-Out (网关超时)"
      case 505:
        return "HTTP Version not supported (HTTP 版本不受支持)"
      default:
        return message
    }
  },
3. 传入时间戳,转换指定的时间格式

这个是本人用的非常多的一个函数,平时经常需要对时间处理,就只需要传入时间戳或者时间格式的字符串,然后指定要转换的时间格式,就可以了,很方便

 用法示例:switchTime(new Date()) // 传入当前时间,默认返回当时时间,格式为 YYYY-MM-DD hh:mm:ss
          switchTime("2018-11-10", "YYYY.MM.DD") // 2018.11.10

 /**
   * 传入时间戳(或者时间格式的数据),转换指定的时间格式
   * @param {Number} val      时间戳(或者时间格式的数据)
   * @param {String} dateType 要得到的时间格式 例如 YYYY-MM-DD hh:mm:ss
   * @return dataStr 例如 YYYY-MM-DD hh:mm:ss
   */
  switchTime: (val = +new Date(), dateType = "YYYY-MM-DD hh:mm:ss") => {
    // 将字符串转换成数字
    let timeStamp, dateStr, str
    timeStamp = +new Date(val)

    // 如果转换成数字出错
    if (!timeStamp) {
      return val
    }

    // 得到时间字符串
    dateStr = new Date(timeStamp)
    str = dateType.replace("YYYY", dateStr.getFullYear())
    str = str.replace("MM", (dateStr.getMonth() + 1 < 10 ? "0" : "") + (dateStr.getMonth() + 1))
    str = str.replace("DD", (dateStr.getDate() < 10 ? "0" : "") + dateStr.getDate())
    str = str.replace("hh", (dateStr.getHours() < 10 ? "0" : "") + dateStr.getHours())
    str = str.replace("mm", (dateStr.getMinutes() < 10 ? "0" : "") + dateStr.getMinutes())
    str = str.replace("ss", (dateStr.getSeconds() < 10 ? "0" : "") + dateStr.getSeconds())

    return str
  }
4. 浏览器打开新窗口

在平时开发中,一定会有这样的需求,打开新窗口。但是用window.open的方式往往会碰到被浏览器拦截的问题,所以可以用a标签通过超链接的方式打开新窗口。
往往在下载文件的时候也会用到这个方法。不过下载文件分为几种情况,一种是直接访问一个地址,浏览器会自动解析并且下载,还有一种情况就是后端返回的是一个文件,这个时候需要先在响应类型中加上blob处理之后,再去处理。这种情况下访问解析后的地址,往往是打开一个新窗口并访问,并不会自动下载,而需要下载的话需要给a标签再加上一个download属性。

  用法示例:openWindow("https://www.baidu.com") // 默认打开方式为新窗口, id为open

  /**
   * a模拟window.open,不会被浏览器拦截
   * @param {String} url        a标签打开的地址
   * @param {String} id         a标签的ID
   * @param {String} targetType a标签点击打开的方式(当前页面打开还是新窗口打开)
   */
  openWindow: (url, targetType = "_blank", id = "open") => {
    // 如果存在则删除
    if (document.getElementById(id)) {
      document.body.removeChild(document.getElementById(id))
    }
    let a = document.createElement("a")
    a.setAttribute("href", url)
    a.setAttribute("download", url)
    a.setAttribute("target", targetType)
    a.setAttribute("id", id)
    document.body.appendChild(a)
    a.click()
  },
5. 将有层级关系的列表转换成树状数据

不知道大家碰到树状结构的情况,但是本人开发的时候,因为开发的平台类的项目较多,所以经常碰到树状的数据结构。
以前都是叫后端直接返回树状数据的,但是后端好像也不喜欢处理这样的数据,就自己写了一个方法。
传入有层级关系的列表数据,然后根据定义的参数,处理成树状的数据结构。

  用法示例:let arr = [{id: 1, pid: 0, name: "一级"}, {id: 2, pid: 1, name: "二级"}],
               arr1 = getTreeArr({key: "id", pKey: "pid", rootPValue: 0, data: arr})
  得到的数据为:
           arr1 = [
               {id: 1, pid: 0, name: "一级", children: [{id: 2, pid: 1, name: "二级", children: []}]
               }
           ]

  /**
   * 将一级的数据结构处理成树状数据结构
   * @param {Object} obj {key, pKey, data}
   *  @param obj.key  字段名称 比如id
   *  @param obj.pKey 父字段名称 比如 pid
   *  @param obj.rootPValue 根节点的父字段的值
   *  @param obj.data 需要处理的数据
   * @return {Array} arr
   */
  getTreeArr: (obj) => {
    if (!Array.isArray(obj.data)) {
      console.log("getTreeArr=>请传入数组")
      return []
    }
    let arr = obj.data, arr1 = []
    // 将数据处理成数状结构
    arr.forEach(item => {
      let index = 0
      item.children = []
      arr.forEach(item1 => {
        // 得到树结构关系
        if (item[obj.key] === item1[obj.pKey]) {
          item.children.push(item1)
        }
        // 判断根节点
        if (item1.id !== item.pid) {
          index++
        }
        // 传入根节点,根据传入的根节点组成树结构
        if (rootPValue in obj && item[obj.pKey] === obj.rootPValue) {
          arr1.push(item)
        }
      })
      // 没传入根节点,根据当前数据结构得到根节点
      if (!(rootPValue in obj) && index === arr.length) {
        arr1.push(item)
      }
    })
    return arr1
  }
6. 占位显示

写vue组件的时候,总是习惯用对象去做参数,因为觉得把参数变成对象的形式维护起来会非常方便,每次增加参数的时候只需要在对象中加上属性,接受的地方对属性做处理就好了。
但是vue组件的话,Object是不能设置默认值的,没有默认值的话,读取对象的属性便是一个错误的语法,所以就写了一个占位显示的方法,比如

  用法示例:showData(obj, "name", "名字") // 当obj未传入的时候显示 ‘名字’, 传入后显示为 obj.name

  /**
 * 用来判断对象不存在是,显示的字段数据
 * @param {Object} obj 对象
 * @param {String} key 要显示的属性
 * @param {String} staticName 属性不存在时显示的值
   */
  showData (obj, key, staticName) {
    if (!obj) {
      obj = {}
    }
    if (obj && obj[key]) {
      return obj[key]
    } else {
      return staticName
    }
  }
7. 数组(对象数组去重)

使用和参数说明

用法示例:handleRepeatArr({data: [1 , 1 ,1]}) // [1]
         handleRepeatArr({data: [{name: 1}, {name: 1}], key: "name"}) // [{name: 1}]
    
  /**
 - 数组去重
 - @param {Array} data 要去重的数组
 - @param {String} key 作为去重依据的字段 (处理对象数组时需要传入)
 - @return arr 返回处理后的数据
   */

1.递归去重(数据无法保持之前的排序)

  handleRepeatArr ({data, key}) {
    if (!Array.isArray(data)) {
      console.log("请传入数组")
      return
    }
    // 先对数据做排序处理
    data = data.sort((item, item1) => {
      if (key) {
        return item[key] - item1[key]
      }
      return item - item1
    })
    // 递归去重
    function getData (index) {
      if (index >= 1) {
        // 判断当前数据和下一条数据是否相等
        let result = key ? data[index][key] === data[index - 1][key] : data[index] === data[index - 1]
        if (result) {
          data.splice(index, 1)
        }
        getData(index - 1)
      }
    }
    getData(data.length - 1)
    return data
  }

2.根据对象的属性不同去重 (推荐使用)

  handleRepeatArr ({data, key}) {
    if (!Array.isArray(data)) {
      console.log("请传入数组")
      return
    }
    let arr = [], obj = {}
    data.forEach((item, index) => {
      let attr = key ? item[key] : item
      if (!obj[attr]) {
        obj[attr] = index + 1
        arr.push(item)
      }
    })
    return arr
  }

3.利用indexOf以及forEach (适合处理数组,不适合处理对象数组)

  handleRepeatArr ({data, key}) {
    if (!Array.isArray(data)) {
      console.log("请传入数组")
      return
    }
    let arr = []
    data.forEach((item, index) => {
      // 如果当前元素在之后没有出现过(后面出现的数据会保留)
      // let result = data.indexOf(item, index + 1)
      // 如果当前元素在之前没有出现过(前面出现的数据会保留)
      let result = index === 0 ? -1 : data.lastIndexOf(item, index - 1)
      if (result === -1) {
        arr.push(item)
      }
    })
    return arr
 }

4.双层循环去重 (占用内存高)

  handleRepeatArr ({data, key}) {
    if (!Array.isArray(data)) {
      console.log("请传入数组")
      return
    }
    for (let i = 0, len = data.length; i < len; i++) {
      for (let j = i + 1; j < len; j++) {
        let result = key ? data[i][key] === data[j][key] : data[i] === data[j]
        if (result) {
          data.splice(j, 1)
          len--
          j--
        }
      }
    }
    return data
 }

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/100439.html

相关文章

  • 阿里云前端周刊 - 第 18 期

    摘要:然鹅在过去的两个月里,对的理解发生了一波三折的变化。发布自版本发布之后,一直致力于提升版本迭代速度,尽可能地通过小的更新来修复存在的问题。 推荐 1. 深入浅出 React 高阶组件 https://zhuanlan.zhihu.com/p/... 由高阶函数引申高阶组件,高阶组件是接受 React 组件作为输入,输出一个新的 React 组件的组件,本文介绍了在 React 工程中如...

    luck 评论0 收藏0
  • 前端】Util.js-ES6实现常用100多个javaScript简短函数封装合集(持续更新

    摘要:在数组中循环使用将数组的第一个元素除去直到函数的返回值为。使用匿名内部函数范围来声明未定义的内存空间使用闭包来存储返回值。返回顶部从数组中移除给定函数返回的元素使用查找返回值的数组元素和以使用删除元素。使用执行从右向左的函数组合。 showImg(https://segmentfault.com/img/bV0PXR?w=400&h=80); Util.js (持续更新中...) ...

    ivyzhang 评论0 收藏0
  • 前端面试题收集,持续更新

    摘要:对于所访问的每个元素,函数应该将该元素传递给所提供的回调函数。 HTML 在线阅读Github地址 题目列表 HTML HTML和XHTML的区别 Html的语义化 Doctype的文档类型 cookie、sessionSttorage、localStory区别 HTML全局属性(global attribute)有哪些? 常见的浏览器内核有哪些? 介绍一下你对浏览器内核的理解?...

    kgbook 评论0 收藏0

发表评论

0条评论

wyk1184

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<