道招

邮箱收件人组件成长历程(二)(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”

相关文章

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

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

项目Vue转成React hooks可能存在的问题--急需类似setState回调

假设在Vue中有如下三个方法,并且初始时 this.a = ‘a’; this.b = ‘b’; funA() { this.a = '1221&#03 阅读更多…

邮箱收件人组件(vue版)成长历程(一)

前期项目中需要优化原始的收件人、抄送、密送部分,换成更加现代化的样式和用户,当时将这部分抽象成一个组件了,最近的需求是发件人也要使用该组件,鉴于发件人比收件人等需要校验的地方和交互习惯变动点较多,进 阅读更多…

WordPress博客项目改用react前端展示

之前自己的主打技术栈是vue全家桶,所以将自己的wordpress博客改成了vue版本服务端渲染,现在因为公司需要将我的项目从vue转到react,本人后面可能也就要主打eact技术栈了。 我记 阅读更多…

Vue和React hooks实现Select批量选择、选中条数、全选、反选实现对比

批量选择、全选、反选这些功能使用频率还是很高的,下面直接看看Vue和React分别怎么实现吧。 Vue 在使用Vue的时候是很容易实现的,我们以下列数据格式为例: const data 阅读更多…

react router页面跳转二次确认弹框及样式、业务逻辑自定义

我们在编辑页面时如果需要跳走通常会需要给用户提示,react router本身已经给了我们这样的功能,我们先看看怎么使用。 初见二次确认弹框 // App.jsx const App = 阅读更多…

关注道招网公众帐号
道招开发者二群