前端基础向~从项目出手封装工具函数

简介: 前端基础向~从项目出手封装工具函数

前言


在项目开始初期,往往都是有组里的“大佬”为我们搭建或者说改造一个项目使用的前端项目框架,通常都会包含一些常用的库和函数:比如 router 路由、store 数据共享、登录和异常页、动态路由和按钮权限处理等等。但是在项目进行过程中,都需要大家一起参与!不管是小白也好、大佬也好,在处理一些基础的表单表格的时候,基本思路和代码逻辑应该都是差不多的。


所以为了统一和复用这部分功能的代码,来减少代码量、降低“小白”们编写代码时会花费的时间,我们都会创建一个 Utils 工具函数目录,用来存放我们抽离出来的所有工具函数。


那么如何抽离和封装一个工具函数呢?我们需要从以下这些步骤开始。


1. 初始的逻辑抽离


这一部分一般都是发生在我们刚刚意识到我们现在编写的这一段代码在以后我可能还会用到的时候,我们会想到的处理方式。


以我项目中的一个例子来说:有一个很大的字典对象,存放了所有前后端定义的字段数组;但是在详情页显示的时候一般都需要通过 value 字段来查找对应的 label。


此时一般都是建立一个函数专门用来查找,或者将字段数组转为 map 格式(目前一般都是用对象)。我们当时选择了第二种方案:


export const Enums = {
  protocolType: [
    { label: "label 1", value: 1 },
    { label: "label 2", value: 2 },
    { label: "label 3", value: 3 }
  ],
  nodeType: [
    { label: "label 1", value: 1 },
    { label: "label 2", value: 2 }
  ]
}
export function arr2map (arr) {
  return arr.reduce((mmap, item) => {
    mmap[item.value] = item.label;
    return mmap;
  }, {});
}
export const EnumsMap = Object.keys(Enum).reduce((eEmap, groupName) => {
  eEmap[groupName] = arr2map(Enum[groupName]);
  return eEmap;
}, {});


这里我们编写了一个函数 arr2map ,用来将我们字典的对象数组转化为一个 value: label 格式的对象。


此时在当前情况下这段逻辑是没有一点问题的。


2. 遇到问题


但是在后来,我们遇到了一个新问题:arr2map 只支持 [{ label: xxx, value: xxx }] 的格式,不能用于其他场景。


所以,我们又对其进行了一次改造(当然,改造必须影响最小化,即不会影响以前的代码,也不需要重新对以前的代码进行修改)


export function notNull(val) {
  return val !== undefined && val !== null;
}
export function arr2map(arr = [], props = { label: "label", value: "value" }) {
  return arr.reduce((mmap, item) => {
    mmap[item[props.value]] = notNull(props.label) ? item[props.label] : true;
    return mmap;
  }, {});
}


这时我们的数组转对象的函数就算是比较成熟了。可以支持一个配置项来控制我们从对象数组中提取对象的哪些元素来生成新的对象。


3. 新的调整


上面的 arr2map 函数,我相信也已经适应了大部分的使用场景。但是,我们又遇到了一个更难受的问题:不只是需要转成 {value: label} 的情况,还需要得到对应字段的所有属性。


比如 [{label: 'label1', value: 1, disabled: true, author: 'xxx'}] 需要转成 { 1: {label: 'label1', value: 1, disabled: true, author: 'xxx'}}


所以此时有需要对 arr2map 进行新的改造。


export function notNull(val) {
  return val !== undefined && val !== null;
}
export function arr2map(arr = [], props = { label: "label", value: "value" }, retain = false) {
  return arr.reduce((mmap, item) => {
    if (retain) {
      mmap[item[props.value]] = item
    } else {
      mmap[item[props.value]] = notNull(props.label) ? item[props.label] : true;
    }
    return mmap;
  }, {});
}


4. 其他挑战


上面的一部分代码我相信大部分的同学都能正确的处理,或者想到更优秀完善的代码。

但是在后续的项目推进中,又接到了产品的一系列新的需求。其中一个就是:根据一个值从树型数组中拿到所有上级节点的 label 值组成一个完整的字符串路径返回。


这个功能一般在 组织机构树、关系树 等场景中。为了做到后续能兼容更多的场景更多的数据类型,所以然需要接收一些配置项。最终的代码如下:


/**
 * 获取一个数据在树形数组中对应的名称 ( 场景:根据code在组织树中查询对应的组织名称 )
 * @param { array } tree 包含子节点的数据对象
 * @param { * } value 当前查询的值, 一般是字符串或者数字
 * @param {{key?: string, label?: string, children?: string}} props 默认关键字(key: 查询值键名,label: 名称键名)
 * @param { ?object } options 配置项
 * @return { string | undefined } 名称
 * */
export function getTreeNodeLabel(tree, value, props = {}, options = {}) {
  let { key = "code", label = "label", children = "children" } = props;
  let { splice = true, hideFirst = false } = options;
  for (let node of tree) {
    if (node[key] === value) {
      return node[label];
    }
    if (notEmpty(node[children])) {
      let res = getTreeNodeLabel(node[children], value, props, { splice });
      if (res) {
        if (hideFirst) {
          return res;
        }
        return splice ? `${node[label]}/${res}` : res;
      }
    }
  }
  return undefined;
}


这里接收两个配置对象:props 和 options。


  • props: 用来配置数据获取以及确认递归对象,保证可以通过配置这几个参数来适应多种属性数据格式


  • options:用来配置输出数据格式;splice 确认是否需要分割线,hideFirst 是否需要隐藏顶级节点


后面其实还可以扩展,如果将隐藏顶级节点 label 改为 隐藏几级节点的label,分割线也可以配置,或者支持用函数来处理等等。


5. 总结


从上面两个场景来看,工具函数主要是 “对业务数据进行处理,得到另外一种预期中的数据格式”,那么 “处理同种业务场景,或者需要统一显示样式等情况,一般都是用封装业务组件来完成。


数据处理(转换),个人感觉最常见的就是对数组或者对象的操作,不管是合并、扁平化等等,在编写这类工具函数的过程中,不仅可以增加我们对编写工具函数时注意事项的理解、也能增加我们对算法、函数式编程的掌握。


目录
相关文章
|
29天前
|
监控 前端开发 数据可视化
3D架构图软件 iCraft Editor 正式发布 @icraft/player-react 前端组件, 轻松嵌入3D架构图到您的项目,实现数字孪生
@icraft/player-react 是 iCraft Editor 推出的 React 组件库,旨在简化3D数字孪生场景的前端集成。它支持零配置快速接入、自定义插件、丰富的事件和方法、动画控制及实时数据接入,帮助开发者轻松实现3D场景与React项目的无缝融合。
105 8
3D架构图软件 iCraft Editor 正式发布 @icraft/player-react 前端组件, 轻松嵌入3D架构图到您的项目,实现数字孪生
|
6天前
|
前端开发 JavaScript 开发者
前端项目代码规范工具 (ESLint. Prettier. Stylelint. TypeScript)
前端项目代码规范工具 (ESLint. Prettier. Stylelint. TypeScript)
|
1月前
|
前端开发 数据处理 Android开发
Flutter前端开发中的调试技巧与工具使用方法,涵盖调试的重要性、基本技巧如打印日志与断点调试、常用调试工具如Android Studio/VS Code调试器和Flutter Inspector的介绍
本文深入探讨了Flutter前端开发中的调试技巧与工具使用方法,涵盖调试的重要性、基本技巧如打印日志与断点调试、常用调试工具如Android Studio/VS Code调试器和Flutter Inspector的介绍,以及具体操作步骤、常见问题解决、高级调试技巧、团队协作中的调试应用和未来发展趋势,旨在帮助开发者提高调试效率,提升应用质量。
50 8
|
1月前
|
前端开发 测试技术
前端工程化的分支策略要如何与项目的具体情况相结合?
前端工程化的分支策略要紧密结合项目的实际情况,以实现高效的开发、稳定的版本控制和顺利的发布流程。
28 1
|
1月前
|
监控 前端开发 JavaScript
前端稳定性工具-Sentry
【11月更文挑战第9天】Sentry 是一个开源的错误和性能监控平台,支持多种编程语言和框架。它能够捕获前端应用中的各种错误和性能问题,提供详细的错误信息和用户行为关联,帮助开发团队快速定位和解决问题,优化应用性能。但需注意隐私保护、数据准确性和成本控制。
|
1月前
|
Web App开发 前端开发 JavaScript
前端开发的秘密武器:这些工具让你轻松应对各种复杂布局!
【10月更文挑战第31天】前端开发充满挑战,尤其是在处理复杂布局时。本文介绍了几种关键工具和技术,如HTML和CSS基础、Firefox开发者工具、Visual Studio Code以及Vue、React和Angular等前端框架,帮助开发者高效应对复杂布局,提升代码质量和用户体验。
36 2
|
1月前
|
前端开发 Unix 测试技术
揭秘!前端大牛们如何高效管理项目,确保按时交付高质量作品!
【10月更文挑战第30天】前端开发项目涉及从需求分析到最终交付的多个环节。本文解答了如何制定合理项目计划、提高团队协作效率、确保代码质量和应对项目风险等问题,帮助你学习前端大牛们的项目管理技巧,确保按时交付高质量的作品。
41 2
|
2月前
|
存储 人工智能 前端开发
前端大模型应用笔记(三):Vue3+Antdv+transformers+本地模型实现浏览器端侧增强搜索
本文介绍了一个纯前端实现的增强列表搜索应用,通过使用Transformer模型,实现了更智能的搜索功能,如使用“番茄”可以搜索到“西红柿”。项目基于Vue3和Ant Design Vue,使用了Xenova的bge-base-zh-v1.5模型。文章详细介绍了从环境搭建、数据准备到具体实现的全过程,并展示了实际效果和待改进点。
188 2
|
2月前
|
JavaScript 前端开发 程序员
前端学习笔记——node.js
前端学习笔记——node.js
54 0
|
2月前
|
人工智能 自然语言处理 运维
前端大模型应用笔记(一):两个指令反过来说大模型就理解不了啦?或许该让第三者插足啦 -通过引入中间LLM预处理用户输入以提高多任务处理能力
本文探讨了在多任务处理场景下,自然语言指令解析的困境及解决方案。通过增加一个LLM解析层,将复杂的指令拆解为多个明确的步骤,明确操作类型与对象识别,处理任务依赖关系,并将自然语言转化为具体的工具命令,从而提高指令解析的准确性和执行效率。