道招

邮箱收件人组件成长历程(二)(React hooks升级版)

如果您发现本文排版有问题,可以先点击下面的链接切换至老版进行查看!!!

邮箱收件人组件成长历程(二)(React hooks升级版)

记得自己之前写过一篇《邮箱收件人组件(vue版)成长历程(一)》记得当时里面写到了自己使用的是可编辑div来进行输入的,同时提到当时出于挑战自己和青铜的倔强,想试着换个方案,完全使用可编辑div来实现。。。这个小小的倔强为后续很多功能瓶颈埋下了隐患。。。 file

使用contenteditable的div缺点

具体的隐患是什么的?

  1. 因为方案中采用的点击插入新收件人时实际上就是向数组里面插入一个空收件人对象,为了确保用户在胡乱点击时永远保证只有一个空对象,就需要频繁的做是否有多余空对象的检查。这个会导致数组频繁的重新渲染,鼠标点入进行选中元素变得很困难。
  2. 普通用户、产品和设计师一般会认为这个收件人组件是一个输入框(你见过谁家的输入框里面能展示校验成功与否的图标的),这会导致他们的需求和改版是以input的某些特性来设计的,这会部分场景用contenteditable的div无法实现,比如用户聚焦后改变整个组件背景颜色。

这次赶上项目迁移至React,对这部分也做了设计上的调整,改用主流的input方法来做输入和编辑态。 响应点击部分还是跟之前一样 file

代码结构

file

  1. 全局只有一个input,解决上述频繁去空检查的问题,将input的输入内容和数组中的某个index进行关联,该index位置就是input内容后续的插入位置,index后面的内容自然向后移动一位。需要编辑或插入内容时,移动input至对应的index。
  2. 在整个组件内但是非已存在收件人信息以外的区域(上图中的蓝框区域)点击时,认为是在最后面添加新的收件人,让input直接移动在列表的最后面,它的输入值会关联到当前收件人数组list的最后一个,关联index为list.length。
  3. 点击到某个收件人预览态(图中的绿框)时将其高亮,如果是双击的化则将其置为编辑态(将input移动到当前收件人位置,并将其数据从list中删除,关联input与该收件人index,待输入完成后再插回此index位置);如果是单击它前面(第一个小箭头所指区域),则是将input移动到它前面,关联input与该收件人index,带输入完成后,将新增内容插入该index。
代码片段:

在变更list数据后React会重新渲染,根据上述代码结构,input会重新出现在列表的最后面,我们需要待渲染完毕后通过图中的ref移动input到它需要出现的位置。

// 回车上屏插入数据
  function onInputEnterInsert(data) {
    const result = getAutoCompleteResult(); // 当前是否选中了搜索候选词
    const finalData = result.value ? result : data; // 如果有候选信息,直接插入候选信息,无视输入信息
    insertData(finalData);
    afterDataInserted(state.inputIndex);
  }

插入数据过程

// 在列表中插入数据
  function insertData(data) {
    const dataInfo = {
      ...data,
      _addedTime: Date.now(), // 方便作为key
    };
    if (isLastIndexOfList(state.inputIndex)) { // 增加新的
      list.push(dataInfo);
    } else { // 双击后更新的
      list.splice(state.inputIndex, 0, dataInfo);
    }
    props.onChange(list.slice()); // 变更state触发渲染
    clearAddress();
  }

渲染后调整input位置

// 在当前inputIndex插入数据后的处理流程
  function afterDataInserted(indexBeforeInsert) {
    console.log('sis hook after inserted -> ', indexBeforeInsert, list[indexBeforeInsert], list);
    typeof afterEditHook === 'function' && afterEditHook(indexBeforeInsert, list[indexBeforeInsert], list);
    // 确保数据变更+input显示后再处理
    setTimeout(() => { // 此时重新渲染后输入框已在最后面
      if (!isLastIndexOfList(indexBeforeInsert)) { // 只要不是在最后面插入的,都需要将列表render后的置于最后面的input移动至当前上次锚定节点的前面
        const targetNode = containerRef.current.children[indexBeforeInsert + 1]; // list里面已经新插入了一个,故原锚定节点的index+1
        containerRef.current.insertBefore(inputContainerRef.current.node, targetNode);
        // dom调整后修正index和input的指向
        dispatch({
          inputIndex: indexBeforeInsert + 1,
        });
      }
      doInputFocus(0);
    }, 0);
  }

可以看到上面还加入了部分hook,方便用户在对应周期处理其它逻辑。 之前的Vue版本在产品迭代过程加入了一些新功能

  1. 列表数量上限
  2. 候选列表只有一个时自动选中
  3. 收件人直接拖动以及跨栏拖动

这部分功能在本次React版本也会同步支持,后面单独写一篇讲一下。

更新时间:
上一篇:Mysql报错“this is incompatible with sql_mode=only_full_group_by”下一篇:wordpress博客提示“Briefly unavailable for scheduled maintenance. Check back in a minute”

相关文章

2021年的一点工作总结(一)迁移React技术栈

2021年全年的工作总结起来很简单,算是做苦力的一年吧。。。 2021年春节后就开始邮件项目从Vue迁移到React的工作以及富文本编辑器由wangEditor替换成CKEditor。 其实自己 阅读更多…

深入学习React时间切片,任务调度scheduler

背景 最近想起月初看到的 魔术师卡颂 (微信号:kasong999)的一个公开直播—— 《手写React优先级调度算法》 ,虽然我更倾向于认为直播内容是演示如何利用React官方同款调度库手写代 阅读更多…

邮箱收件人组件成长历程(三)跨栏拖拽不同数据方案对比

前几天写了收件人组件,它实际就是一个既能输入搜索又能标签形式展示的组件,我称它为SmartInputSelect(以下简称sis组件),在实现下列需求时遇到了些问题,需求就是想实现多个sis组件的邮 阅读更多…

React router用hooks读取routeName、根据routeName跳转

在迁移Vue至React的过程中遇到了一些路由相关的问题,在Vue项目中经常会使用routeName,毕竟使用path太长了,也记不住,我自己看了看React router也没有发现routeNam 阅读更多…

改造富文本编辑器wangEditor成react组件

我们知道wangEditor常用的功能是editor实例的 txt.html() 和 txt.text() 方法,尤其是 txt.html() 方法,这是一个类似与jQuery常用的那种get和se 阅读更多…

React执行调度流程梳理笔记

触发更新 我们最常见的触发更新的方式就是更新state了,可以分别从类组件和函数组件看看这时会发生什么。 类组件之 setState: 当触发 setState 本质上是调用 enque 阅读更多…

关注道招网公众帐号
友情链接
消息推送
道招网关注互联网,分享IT资讯,前沿科技、编程技术,是否允许文章更新后推送通知消息。
允许
不用了