对简书官网个人中心页面右侧内容块tab切换bug的分析

首先声明这是一篇技术分析文章,要输出的信息就是如何分析定位web页面缺陷,并无其它恶意哦@简叔。

事情是这样的,某天我女朋友在电脑上浏览自己简书文章阅读量时发现,最新文章,最新动态,热门文章三个tab选项来回切换时,tab项的选中状态有问题。我一听立马就激动起来了(原谅我,职业病犯了),心想简书这么优秀的平台怎么可能会有这种bug呢?打开简书的web页面看了下,果真存在这个问题,平时都没留意过,不得说女朋友还真是个心细的菇凉(微笑脸)。

背景介绍完了,下面就进入分析过程了。

bug复现

这里就拿@简叔大人的主页来做分析了。进入@简叔的主页你会发现右侧内容首页展示的是最新文章的列表,顶部的tab选项默认选中了最新文章项。为啥?因为最新文章下面有明显的黑色下划线啊,就是下图红色框中的样子。

图1:首次进入默认选中最新文章tab项

然后你再点一下最新动态的选项,你看到了什么,当然是@简叔在简书里面的最新动态了。but,不知道你有没有发现顶部的tab选项为啥有两项都是选中状态,也就是下图红色框中的样子(如果bug还没修复的话)。

图2:tab切换bug复现

这里的现象就是这篇文章要讨论的主角了。正常交互应该是用户查看最新动态时,只有最新动态这一项是选中状态,其它项都是非选中状态,因为下面的内容列表一次只能显示一种类型的内容。

好了,既然bug已经复现,下面我们就来分析下bug出现原因以及解决办法。

bug分析

碰到这种页面问题,我们程序猿要做的一件事情是什么?当然是打开浏览器的开发者工具了,没有意外的话应该是按下快捷键F12,这里使用的google浏览器,当然你也可以使用任何webkit内核的浏览器来调试。

点击开发者工具中控制台上的选择元素按钮,然后把鼠标放到最新文章tab选项上,点击之后你会在控制台的Elements项下发现对应的html代码,应该就是下图中的样子。我们可以发现,这个tab切换使用了很常见的ul li结构实现。每一个tab项都是一个li元素,对于选中的tab项,会在对应的li元素上加一个active类,所以我们可以发现包裹最新文章最新动态li元素上都有active类名。为啥会这样啊?因为这是一个bug啊。为啥这么明显的bug没发现呢?因为程序猿着急上线,加班加点忙到半夜,忘了还有一个bug没改,直接就上线了,上完线直接回去睡觉了,产品经理没有回归体验啊,好吧,这些都是我瞎猜的。其实这个bug的诱因就是用户在点击最新动态tab项,给这个tab项增加active类时,没有清除其它tab项上的active类。具体的原因下面的解决方法中会有分析。

图3:bug分析

心细的读者会发现包裹tab项的a标签上有data-pjax属性,熟悉H5的同学应该对pjax技术并不陌生,就是一种利用H5中的pushState方法以及ajax技术无刷新更新页面数据的技术,具体看以参看jquery的pjax插件,github地址点这里

bug解决方法

bug都分析完了,下面就是来看看能不能找到解决方法了。我们在bug分析的时候知道,在用户点击tab项时会给li元素增加一个active类,这个类肯定是在tab项的点击事件触发时候添加到li标签上的,所以在这个页面对应的业务js代码中肯定会有active这个字符串,知道这个下面就容易了,我们只要找到业务js代码,然后在业务js代码里面搜索active字符串,就可以定位到tab项点击事件处理代码位置了。

打开开发者工具控制台选择Sources项,我们会发现简书网站从很多域加载文件,这么多域我如何才能快速找到业务代码呢?其实现在稍具规模的网站的都会使用cdn来存放自己站点需要的静态资源来加速站点访问,cdn服务一般来说都会利用二级域名做映射,当然不排除也有例外。知道这个点,我们就可以知道要在那个域中找业务js代码了。简书站点相关静态文件存放在cdn.qn0.jianshu.io域下,打开这个域下的每一个js文件,然后搜索"active"字符串,找到含有这个字符串的js文件,然后利用开发者工具自带的代码美化工具把压缩的js代码重新格式化排版,然后你就会发现下图中的代码片段。

图4:bug代码定位

在业务js代码中我们会发现下面这段代码:

$("#list-container").on("pjax:success", function(t) {
       return function(n) {
            var r;
            return $("ul.nav-relationships li").removeClass("active"),
                    r = $(n.relatedTarget),
                    r.parent().addClass("active"),
                    $(window).scroll(),
                    e.initSharedAt(),
                    t.infiniteScroll()
     }
}(this))

每次pjax执行成功之后都会执行这段事件处理代码,在代码中我们也可以发现有$("ul.nav-relationships li").removeClass("active"),这种操作,但是为啥没生效呢?别急,我们来看下这里的removeClass是对那个标签元素操作的。我们把这里的选择元素的操作$("ul.nav-relationships li")放到开发者工具控制台执行下,就会发现这里的选择器并没有找到元素,对空元素进行removeClass当然不生效了。

回到图3的步骤,我们发现包裹tab项的ul标签中并没有nav-relationships这个类,ul标签是这样的<ul class="nav nav-tabs nav-articles">,也就是说通过nav-relationships类是找不到包裹tab项的ul标签的,我们可以使用nav-articles类来寻找包裹tab项的ul标签。

事件处理代码改成下面的样子:

$("#list-container").on("pjax:success", function(t) {
       return function(n) {
            var r;
            return $("ul.nav-articles li").removeClass("active"),
                    r = $(n.relatedTarget),
                    r.parent().addClass("active"),
                    $(window).scroll(),
                    e.initSharedAt(),
                    t.infiniteScroll()
     }
}(this))

然后就可以解决这个问题,上面的代码已经通过代码注入的方式验证可以解决这个bug,这里就不详细说了。

导致这个问题最有可能的原因就是写页面样式和写页面业务js代码的不是同一个人,写页面业务js代码的人使用静态页面样式中的一个类来查找元素,第一版的时候不会有问题,但是一旦后续版本页面样式有更新,而写页面业务js代码的人不知道那些地方更新了,直接拿来集成了,就会导致这种查找不到元素的问题,这也告诫写业务js代码的人尽量不要用那些用来渲染样式的选择器来查找元素,不要怕麻烦,自己重新定义选择器。

全文完。

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

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,598评论 25 707
  • 问答题47 /72 常见浏览器兼容性问题与解决方案? 参考答案 (1)浏览器兼容问题一:不同浏览器的标签默认的外补...
    _Yfling阅读 13,635评论 1 92
  • 前端开发面试知识点大纲: HTML&CSS: 对Web标准的理解、浏览器内核差异、兼容性、hack、CSS基本功:...
    秀才JaneBook阅读 2,251评论 0 25
  • 第5章 菜单、按钮及导航 一、下拉菜单 小伙伴们注意,在Bootstrap框架中的下拉菜单组件是一个独立的组件,根...
    凛0_0阅读 4,869评论 0 66
  • 我是一位普通的不能再普通的家庭农妇。 去年,刚上初中的儿子放暑假后,就和他几个小学同学混在了一起。 那几个孩子四、...
    小头头阅读 226评论 2 3