美文网首页程序员的日常Web前端之路程序员
对简书官网个人中心页面右侧内容块tab切换bug的分析

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

作者: 留七七 | 来源:发表于2016-12-19 23:08 被阅读477次

    首先声明这是一篇技术分析文章,要输出的信息就是如何分析定位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代码的人尽量不要用那些用来渲染样式的选择器来查找元素,不要怕麻烦,自己重新定义选择器。

    全文完。

    相关文章

      网友评论

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

      本文链接:https://www.haomeiwen.com/subject/ointvttx.html