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

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

前言


在项目开始初期,往往都是有组里的“大佬”为我们搭建或者说改造一个项目使用的前端项目框架,通常都会包含一些常用的库和函数:比如 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. 总结


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


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


目录
相关文章
|
25天前
|
JavaScript 前端开发 Docker
前端全栈之路Deno篇(二):几行代码打包后接近100M?别慌,带你掌握Deno2.0的安装到项目构建全流程、剖析构建物并了解其好处
在使用 Deno 构建项目时,生成的可执行文件体积较大,通常接近 100 MB,而 Node.js 构建的项目体积则要小得多。这是由于 Deno 包含了完整的 V8 引擎和运行时,使其能够在目标设备上独立运行,无需额外安装依赖。尽管体积较大,但 Deno 提供了更好的安全性和部署便利性。通过裁剪功能、使用压缩工具等方法,可以优化可执行文件的体积。
103 3
前端全栈之路Deno篇(二):几行代码打包后接近100M?别慌,带你掌握Deno2.0的安装到项目构建全流程、剖析构建物并了解其好处
|
7天前
|
监控 前端开发 JavaScript
前端稳定性工具-Sentry
【11月更文挑战第9天】Sentry 是一个开源的错误和性能监控平台,支持多种编程语言和框架。它能够捕获前端应用中的各种错误和性能问题,提供详细的错误信息和用户行为关联,帮助开发团队快速定位和解决问题,优化应用性能。但需注意隐私保护、数据准确性和成本控制。
|
14天前
|
前端开发 JavaScript API
前端开发的秘密武器:这些工具让你轻松应对各种复杂动画效果!
【10月更文挑战第30天】前端开发中,动画效果为页面增添了无限生机。CSS3的@keyframes规则和JavaScript动画库如GSAP、Anime.js等,使开发者能轻松实现从简单到复杂的动画效果。掌握动画原理和设计原则,结合工具和库,可以创造出既美观又实用的动画,提升用户体验。
37 4
|
13天前
|
Web App开发 前端开发 JavaScript
前端开发的秘密武器:这些工具让你轻松应对各种复杂布局!
【10月更文挑战第31天】前端开发充满挑战,尤其是在处理复杂布局时。本文介绍了几种关键工具和技术,如HTML和CSS基础、Firefox开发者工具、Visual Studio Code以及Vue、React和Angular等前端框架,帮助开发者高效应对复杂布局,提升代码质量和用户体验。
25 2
|
14天前
|
前端开发 Unix 测试技术
揭秘!前端大牛们如何高效管理项目,确保按时交付高质量作品!
【10月更文挑战第30天】前端开发项目涉及从需求分析到最终交付的多个环节。本文解答了如何制定合理项目计划、提高团队协作效率、确保代码质量和应对项目风险等问题,帮助你学习前端大牛们的项目管理技巧,确保按时交付高质量的作品。
28 2
|
1月前
|
自然语言处理 前端开发 JavaScript
推荐 10 个前端开发会用到的工具网站
本文介绍了多个前端开发工具,包括 Web Design Museum、Landing Page、Google Fonts、Lorem Ipsum、Animista、Blobmaker、Spline、CodeToGo、UnusedCSS 和 Responsively,帮助开发者提高效率和项目质量。这些工具涵盖了设计、动画、代码片段管理、响应式测试等多个方面。
69 0
推荐 10 个前端开发会用到的工具网站
|
26天前
|
缓存 前端开发 JavaScript
前端架构思考:代码复用带来的隐形耦合,可能让大模型造轮子是更好的选择-从 CDN 依赖包被删导致个站打不开到数年前因11 行代码导致上千项目崩溃谈谈npm黑洞 - 统计下你的项目有多少个依赖吧!
最近,我的个人网站因免费CDN上的Vue.js包路径变更导致无法访问,引发了我对前端依赖管理的深刻反思。文章探讨了NPM依赖陷阱、开源库所有权与维护压力、NPM生态问题,并提出减少不必要的依赖、重视模块设计等建议,以提升前端项目的稳定性和可控性。通过“left_pad”事件及个人经历,强调了依赖管理的重要性和让大模型代替人造轮子的潜在收益
|
1月前
|
存储 人工智能 前端开发
前端大模型应用笔记(三):Vue3+Antdv+transformers+本地模型实现浏览器端侧增强搜索
本文介绍了一个纯前端实现的增强列表搜索应用,通过使用Transformer模型,实现了更智能的搜索功能,如使用“番茄”可以搜索到“西红柿”。项目基于Vue3和Ant Design Vue,使用了Xenova的bge-base-zh-v1.5模型。文章详细介绍了从环境搭建、数据准备到具体实现的全过程,并展示了实际效果和待改进点。
130 2
|
1月前
|
JavaScript 前端开发 程序员
前端学习笔记——node.js
前端学习笔记——node.js
38 0
|
1月前
|
人工智能 自然语言处理 运维
前端大模型应用笔记(一):两个指令反过来说大模型就理解不了啦?或许该让第三者插足啦 -通过引入中间LLM预处理用户输入以提高多任务处理能力
本文探讨了在多任务处理场景下,自然语言指令解析的困境及解决方案。通过增加一个LLM解析层,将复杂的指令拆解为多个明确的步骤,明确操作类型与对象识别,处理任务依赖关系,并将自然语言转化为具体的工具命令,从而提高指令解析的准确性和执行效率。