Mint-ui框架中<mt-index-list>组件索引值排序混乱bug的解决方案

bug背景

最近接手公司的cordova老项目,项目中用到了f7和mint-ui,其中有一个页面大致是这样的


学生列表

这个首字母列表和右侧的首字母索引是<mt-index-list>提供的,template代码大致为

<mt-index-list :class="{itemRed: hasHeart}">
    <!-- 其中firstLetterArr为首字母列表,firstData为根据首字母区分开的列表项,都是computed中的属性 -->
    <mt-index-section v-for="(letter,indexs) in firstLetterArr" :key="indexs" :index="letter">
    <!-- <mt-index-section v-for="letter in firstLetterArr" :key="letter" :index="letter"> -->
        <in-school-list-item v-for="item in firstData[letter]" :key="item.user_id" :item="item"/>
    </mt-index-section>
</mt-index-list>

bug表象

1.首先上述template代码使用注释掉的那行,也就是这样:

<!-- 基本操作,v-for的key用唯一属性值 -->
 <mt-index-section v-for="letter in firstLetterArr" :key="letter" :index="letter">
  1. 当上述学生列表为全部的时候,假设右侧索引值对应为 CKW# (其中#为数字或特殊符号)
  2. 增加筛选项,过滤掉部分数据,使右侧索引值变为 C#
  3. 解除筛选项,恢复全部学生列表,右侧索引值 期待 变为 CKW#,实际变成 C#KW

bug解决的过程

WOC!为啥是这样的,一开始以为是自己的compute属性逻辑有bug,然后我一个个打印解除筛选项后的首字母列表,发现一直都是CKW#,并没有发生什么异常,然后我第一想法是diff算法出现了啥猫腻,但是又感觉解释不通,除此之外又无从下手,我抱着侥幸的心理,改了一下v-for的key值:

<mt-index-section v-for="(letter,indexs) in firstLetterArr" :key="indexs" :index="letter">

然后bug没了。。。是的,就是这么简单,用index取代item作为key值,能够修复列表项变动导致的<mt-index-list>乱序bug

bug产生的原因

我是个不找到问题原因就睡不着觉的白痴,完全无法停止思考。以下是我的思考历程:

  1. 错误的原因分析:
    diff算法和vue原理理论上我掌握的还凑合,但是不能有效的对应实际应用,再加上我没有认真看<mt-index-list>组件的结构,导致一开始我越思考就离真相越远。。。我甚至觉得,他这和diff没关系,他是通过Vnode的key和组件接收到的首字母进行了一种神秘的排序,才造成这种有实际key值时,新的索引会加在原有索引后面的bug,反之当key和首字母不相等的时候再返回正常的排序。。。我甚至自己模拟出了这种智障排序的实现历程。。。还真能做到!但是这只是个简单的ui组件库啊。。。他的作者真的会想这么多然后刻意地写一个bug吗?

  2. 正确的原因分析:
    肯定是我想歪了,怎么想key对应的最直观的就是diff算法吧,然后冷静分析组件结构!最外层的<mt-index-list>是个壳子,内层的<mt-index-section>代表一个首字母对应的Group,然后最里面是自己的列表项<in-school-list-item>。嗯,重点来了。。。右边的索引在哪?因为最外层的组件没有接受首字母相关的参数,我推断索引是<mt-index-section>的兄弟组件(这里我没看源码),索引是通过<mt-index-section>操作父组件或者兄弟组件生成的。但是为什么会有这样的bug呢?

对diff算法不了解的同学可以看下我的这篇关于Vue中diff算法的文章,看完了你可能就更不了解了~

产生问题的原因是什么呢?

使用item作为key值,最后由 C#(对应key值为C、#) 变为 CKW#(对应key值为C、K、W、#) 的过程,diff的判断流程是C和C相等,#和K不相等,#和#相等,diff结束,创建节点K,创建节点W,节点的创建顺序是C => # => K => W,CKW#每个对应的都是单独的<mt-index-section>组件,都会有自己的生命周期,所以他们对索引的添加顺序也会受到diff算法的影响,导致最后的索引变成 C#KW,出现bug

使用index作为key值,最后由 C#(对应key值为0、1) 变为 CKW#(对应key值为0、1、2、3) 的过程,diff的判断流程是C和C相等(0 == 0),#和K相等(1 == 1),diff结束,创建节点W,创建节点#,节点的创建顺序是C => K => W => #,一切又恢复正常。

原理和bug本身都很简单,记录和分享自己成长的历程~
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 221,198评论 6 514
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,334评论 3 398
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 167,643评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,495评论 1 296
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,502评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,156评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,743评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,659评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,200评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,282评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,424评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,107评论 5 349
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,789评论 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,264评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,390评论 1 271
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,798评论 3 376
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,435评论 2 359

推荐阅读更多精彩内容