我不知道之---includes

998 阅读6分钟

关于什么是 includes 这件事?

🙄 当然是面向MDN编程

Array.prototype.includes()String.prototype.includes()TypedArray.prototype.includes()

【第三个我真不知道,mdn了一下才知道--->咦?我不知道我不知道

文案性质:工作里的日常总结~

写作小目标:用极简单的代码,描述尽可能多的使用场景~

我不知道之-includes 在日常业务中的使用

好了,一个一个来,先上 Array.prototype.includes()

curd-场景值筛选

增删改查表单数据时,通常会看到如下情况

image.png

操作情景可能会是

编辑、查看、发布、提审、下架、上架、下载、上传、删除、屏蔽、加入黑名单、移除、邀请、配置、升舱、归档、回收、清零、重置、灰度处理等等;

针对如上可操作性,一般的做法就是后端返回一个字段比如:state/type/editType/xxxxxx,来给定当前数据的可操作状态,此时,具体的业务场景就来了。某某产品【我希望XXXX(此处省略1w字)】

总结一下就是

  • 当前数据处理A状态时,1,2,3,4可操作,5,6,7不可操作;
  • 当前数据处于B状态时,1,2,3,4不可操作,5,6,7可操作;
  • 当...【当个der~🎃】

祖传代码【N手货】写法

if (state === 'A状态' || state === 'C状态' || state === 'D状态') {
    // 设置1,2,3,4可操作,5,6,7不可操作;
}
if (state === 'B状态' || state === 'M状态' || state === 'N状态') {
    // 设置1,2,3,4不可操作,5,6,7可操作;
}
if (state === 'X状态' || state === 'O状态' || state === 'P状态') {
    // 设置1,2,3,4不显示,5,6,7显示;
}

当接手这段代码时,第一感觉是:【还行、还好、T喵的能看懂👻】,之后为了更好的维护这段代码在最前方添加了注释: A:代表xx状态,B:代表xx状态,C...

由于是多人维护,过了一段时间再来看这段代码时,虽然看上去没什么问题,但总感觉哪里怪怪的:

if (state === 'A状态' || state === 'C状态' || state === 'D状态' ||  || state === 'xx状态' || state === 'xy状态' || state === 'yx状态' || state === 'yy状态') {
    // 设置1,2,3,4可操作,5,6,7不可操作;
}
// ...【不可描述的迭代内容】

真正去读这段代码的时候,才发觉绕的难受...【此后一段时间内,就这样处置,其实就是当时不知道这里可以去优化,去简化读的步骤】,直到看到别人的代码中这样写:

if ([0,1,2].includes(type)) {
    // a展示,bc不展示
}

第一感觉【我T喵的怎么没想到,这方法我知道啊,我居然不知道我知道😩】,果断优化祖传代码

// 优化前
if (state === 'A状态' || state === 'C状态' || state === 'D状态' ||  || state === 'xx状态' || state === 'xy状态' || state === 'yx状态' || state === 'yy状态') {
    // 设置1,2,3,4可操作,5,6,7不可操作;
}
// ...【不可描述的迭代内容】
-------------------------------------------------------------------------------------------
// 优化后
if ([A,C,D,xx,xy,yx,yy].includes(state)) {
    // 设置1,2,3,4可操作,5,6,7不可操作;
}
// ...【优化后的迭代内容】

感觉der一下就上来了,不过觉得还可以再搞点事【此后就是个人尝试了,未添置进实际项目中,不要问,问就是时间、工时各种因素成本】so:

// 抽一个js文件,存放对应文件各种情况列表的汇总
// 例如:
/**
    normalList(正常情况下按钮状态列表):[A,C,D,xx,xy,yx,yy]
    specialList(正常情况下按钮状态列表):[A,C]
*/
/**
  - 此处也可以封装成对象,感觉凭借个人喜好吧
  - AfileStateObj(A文件的状态队形): {normalList: [...],  specialList: [...]}
  
  - 接下来的描述看不明白也没关系,我自己胡思乱想的内容:
  - 对象的话就可以进一步组装全局的<状态属性>管理
  - 每个子文件的各种状态对应一个对象即可
  - 可以从接口获取那就更好,直接动态配置
  - 在对应的管理后台搭建可视化页面,对不同页面状态值进行动态管理,就更好不过了
  - 目前能想到的就到这一层了,如果有其他见解欢迎评论区指出~
  - ...扒拉扒拉,各种优化😂
  
*/
const editTypeList = [A,C,D,xx,xy,yx,yy];
const updateTypeList = [B,M,N];
const showTypeList = [X,O,P];

// 此时的判断更新为
if (editTypeList.includes(state)) {
    // 设置1,2,3,4可操作,5,6,7不可操作;
}
// ...【抽取常量后的迭代内容】

关卡、校验、检索

最常用的,莫过于图片、视频、音频上传的格式校验,下面看下antDesign示例的部分代码: 参考地址---> 用户头像

// ant 官方代码base3.26.19
function beforeUpload(file) {
  const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';
  if (!isJpgOrPng) {
    message.error('You can only upload JPG/PNG file!');
  }
  ...
}
-------------------------------------------------------------------------------------------

// 到实际项目中时,可能就长这样了【仅做示例说明,不代表真实代码】
function beforeUpload(file) {
  // 常见视频类型 MP4/WebM/Ogg
  const isVideo = file.type === 'video/mp4' || file.type === 'video/webm' || file.type === 'video/ogg';
  if (!isVideo) {
    message.error('You can only upload MP4/WebM/Ogg file!');
  }
  ...
}
-------------------------------------------------------------------------------------------

// 优化思路同上,迭代后
function beforeUpload(file) {
  const allowTypeList = [ 'video/mp4', 'video/webm', 'video/ogg' ];
  if (!allowTypeList.includes(file.type)) {
    message.error('You can only upload MP4/WebM/Ogg file!');
  }
  ...
}
-------------------------------------------------------------------------------------------

// em...if中的代码有点长,再精简一下
function beforeUpload(file) {
  const allowTypeList = [ 'video/mp4', 'video/webm', 'video/ogg' ];
  
  // file 解构了一下,布尔值在if外拿一下
  const { type } = file;
  const falg = allowTypeList.some(t => type.includes(t))
  if (!falg) return message.error('You can only upload MP4/WebM/Ogg file!');
  ...
}

这里稍加修改,就可以实现文件图片的切换校验

// typeName 枚举为: 'images'-[代表图片类型]、'files'-[代表文件类型]
function beforeUpload(file, typeName) {
  // 文件列表
  const fileList = ['.doc', '.docx', '.xls', '.txt', '.html', '.pdf'];
  // 图片列表
  const imagesList = [ '.jpg', '.png' ];
  // 获取传入类型关联列表
  const fileType = typeName === 'files' ? fileList : imagesList;
  const { type } = file;
  const falg = fileType.some(t => type.includes(t))
  if (!falg) {
      // notification 为ant的通知提醒框
      notification.error({
        message: `不可上传文件的类型为${
          fileList.join(',')
        }以外的格式${typeName === 'file' ? '文件' : '图片'}`,
      });
      return false;
  }
  ...
}

若遇到其他新的使用场景后,此处补充~

下面是String.prototype.includes() 的场景总结:

字符串匹配

这里的 "字符串" 在业务中可能就变成了:

  • 路由地址,如:/login、/detail等
  • 方法名称:如:getMD5,getUserName等
  • 模块名称或文件名称:如:XX.scss/xx.less/xx.html/xx_modules等
  • 对象属性名称:如:state、flag、isTrue等
  • 具体的网络状态:如:404,502,'error','Not xxxx'等
  • 特殊符号...

x钉、x宝、XX会议,登陆选项中大部分存在三方登陆入口,比如:微信一键登陆等等;然而登陆完依旧要绑定手机号才能正常使用。即:用户登陆后,却检测到其未绑定手机号,直接拦截后,跳去手机号绑定页面【中间一系列的校验操作此处不做讨论】

// 代码可能长这样【也可能长其他样~🧐】
// 假设当前页面为一键登陆页面【可能为某软件,某运营后台,某Sass平台等等】
const loginUrl = 'xxx/yyy/login'; // 绑定手机号页面
const mobile = apiInfo.mobile; // 点击一键登陆时,通过接口获取的手机号
const currentPath = location.pathname;
// 木有手机号 && 当前路径不是绑定手机号页面
if (mobile === '' && !loginUrl.includes(currentPath)) {
    // ...
    // 跳转到绑定手机号页面
}

遇到有趣的例子,此处会再做补充,欢迎留言交流讨论~😋