道招

邮件项目左侧tab切换,右侧主体内容联动的技术实现思考过程

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

邮件项目左侧tab切换,右侧主体内容联动的技术实现思考过程

大家都使用过outlook,在outlook的左侧会有各种文件夹(比如收件箱、已发送邮件),点击文件夹,右侧会打开对应文件夹内的邮件,切换不同文件夹,会继续打开之前打开的邮件。

file

我们自己的邮件项目怎么实现类似的功能呢?

背景

我们的需求有以下几点:

  • 实现上述outlook类似的功能,只是我们的不叫文件夹,叫tab,在对应的tab下未曾打开过邮件的话,就直接显示空态(NoMail);如果上次打开过邮件这重新打开该邮件;如果通过操作将邮件从当前tab转移了(比如将“待处理”的邮件删除后,该邮件进入“已删除”),因为之前打开的邮件已经不在属于此tab了,该tab需要显示空态。这个功能为了方便描述,后面我们称之为联动,也就是左边tab和右边窗口主体内容联动。

file

file

  • 因为“已删除”里面邮件是支持“恢复邮件”的操作,恢复后的邮件会进入“待处理”tab,客服可以重新对它进行回复。为了方便客服,此时不用将右侧主体切换为空态(如果根据联动的话,该邮件已经不在属于“已删除”tab),而是直接以待处理态显示该邮件,若客服后面切换至其它tab再切回“已删除”时,才遵从联动要求,右侧主体不显示该邮件。

file

现状

项目中已经通过消息来实现一个移动机制了,能够将一个邮件从一个tab移动至另一个tab。

下面以删除“待处理”的邮件这一操作为例,此时目标邮件会从“待处理”tab移动至“已删除”tab。

各个tab(“待处理”,“已删除”)会监听一个“MOVE”的消息,该消息内容如下


{
    mailId: 'aaa',
    targetTabName: 'deleted',
}

因为一个邮件在任何时候只会隶属于唯一一个tab,所以我们各个tab在收到上述消息后,除了“已删除”tab的tabName为“deleted”,是和消息体中的targetTabName一致,其它的都不满足,不满足的tab将列表中mailIdaaa的邮件(如果有的话)删掉;而满足条件的“已删除”列表将列表中mailIdaaa的邮件(如果有的话)更新成最新状态,如果当前tab没有这个邮件,这将该邮件插入到tab里面。

需求实现

我们可以将需求简单归纳成以下几点

  • 切换tab时,如果有上次打开邮件的记录,则右侧继续打开该邮件
  • 如果右侧需要打开或者已经打开的邮件,不属于当前tab了,将右侧显示为空态
  • 右侧打开的邮件的需要进行记录,方便再次切换至该tab时重新打开
  • “已删除”tab的邮件需要特殊处理,刚恢复的时候,即使其不再属于“已删除”tab,暂时无视联动规则,依然能成功打开,但是切换tab再切换tab时,遵从联动规则

如果我们按照技术实现来理解需求的话,大致是这样的:

  • 大多数情况下,当前打开的邮件需要满足其隶属于当前激活的tab这一条件,如果不满足则右侧显示空态;满足则能打开,并对其进行记录,方便下次切换到该tab时继续打开。 我们需要设计一个是否满足这一条件的检测机制,这套机制可以借助已有的移动机制,因为将邮件从一个tab移动至另一个tab的过程中,我们可以知道目标邮件已经不再属于当前tab了,可以顺便做切换至空态的操作。 用一个对象tabRouteMap来存储各个tab的上次路由即对应的mailId,然后提供一个setTabRouteMap的方法来更新这个对应关系。
    const tabRouteMap = {
    pending: {
        routeName: 'NoMail', // 空态
        mailId: '',
    },
    completed: {
        routeName: 'ReplyMail', // 回复邮件态
        mailId: 'aaa',
    },
    deleted: {
        routeName: 'ViewMail', // 查看邮件态
        mailId: 'bbb',
    },
    }
  • “已删除”列表刚恢复的邮件,可以临时跳过上述检测机制。页面的切换时根据react的路由来实现的,切换路由时同步更新tabRouteMap对象。为了实现这一特殊逻辑,我们可以改动下调用setTabRouteMap方法后的流程,在调用setTabRouteMap时先发送一个tabRouteMapUpdate的消息给各个tab,消息内容如下:
    {
    targetTabName: {
        "deleted",
    },
    payload: {
        routeName: 'ViewMail',
        mailId: 'bbb',
    }
    }

    各个tab收到tabRouteMapUpdate消息后,如果是目标targetTabName的tab,就需要检测payload里面的mailId是否属于当前tab,如果是的话,回传一个tabRouteMapUpdateConfirm消息,收到回传的确认消息后才更新tabRouteMap对象;如果没能收到确认消息,则不对tabRouteMap对象更新。 基于这个我们就可以在“已删除”tab中刚恢复的邮件的相关路由跳转时不更新tabRouteMap对象,此时的tabRouteMap对象还会继续保留在移动机制更新的空态记录,这也就满足了切换至其它tab再切换“已删除”时,直接打开空态了。

总结

先认真理解产品需求,然后将它无损地翻译成基于技术实现的技术版需求,再看看现有的技术实现是否能通过扩展后满足新需求,如果能的话更好,不能的话就需要考虑是不是对原来的逻辑进行重构或者新开一条机制来辅助实现新需求。

更新时间:
上一篇:下一篇:

相关文章

关注道招网公众帐号
联系博主