从人如何思考看程序员解决问题的思路 - 论原理的重要性

威林厄姆教授的《为什么学生不喜欢上学》中阐述了,思考是把环境信息和长期记忆信息进行重新加工的过程。长期记忆是你对已有知识经验的认知,包括事实性知识和过程性知识。当某个问题超出了你的认知范围时人是没有办法思考的(譬如问你鲁菜中的清汤如何能做到煮时无泡沫)。所以对基础知识(事实性知识)的学习是有必要的。推演到技术上,很多前端前辈强调面试很看中面试者解决问题的能力和思路,但是这些都不是凭空产生的。你必须要知道很多的基础知识和日积月累的项目经验(过程性知识),才有可能通过推理把你存在长期记忆中的基础知识和面临的问题进行结合来解决问题。你不可能让一个完全不知道 HTTP 协议的人回答“当你在浏览器敲下地址后会发生什么”。

以下用一个我自己 debug 的实例来说明下基础知识(原理)和经验发挥的作用。

项目技术背景:

移动端页面,使用 react 和 material-ui,淘宝 lib.flexible 做移动端适配。

bug现象

当页面加载时,按钮上的字会从下往上升的动画效果,见下图:

bug.gif

对于这个问题 debug 的思路及分析步骤如下:

  1. 看上去是一个动画效果,通常是 js 修改了 css 某个属性引起的。我们项目自己代码没有加过动画,查了下元素 css 看到 material-ui 在元素上加了 transition:all 450ms cubic-bezier(0.23, 1, 0.32, 1) 0ms,根据 all 这个值,难以推测是哪个 css 属性变化引起的动画。

  2. 现象是在页面加载完后立即发生的,按经验一般要么是 dom ready 的时候,要么是组件的 componentDidMount 中写有 js 去修改了元素样式。先去 componentDidMount 中逐一注释代码,幸运的是通过注释找到了产生此现象的函数调用。

  3. 查看步骤2中定位出来的函数,其中有一句是获取某个元素的 offsetHeight,就是这条语句触发了这个 bug(注释掉此行代码,现象消失),而获取一个元素的 offsetHeight 会导致页面 reflow。我猜测是这个 reflow 导致某个不应该生效的样式生效了,但是此时依然无法定位那个样式的变化导致这个 bug。

  4. 仔细查看此按钮的样式,在我的知识范围里面没有找出可疑的样式(这里就是我此次 debug 的难点,因为导致此 bug 涉及到的一个 css 特性我不知道)。但是经过我对自己已知 css 知识的排查,猜测可能是行高引起的问题,并不经意间看到 body 设置了一个不太常见的 inline style:font-size: 12px。我想验证下是否是字体大小影响了垂直居中。所以我起 demo 测试获知:一般来说一个 div 高度和行高一样时,内部文字会垂直居中,但是前提是这个 div 的字体要小于高度。如果字体大于高度则文字会在中心线以下(具体原理还不清楚,遂记录下来,需要去调研下行高和字体的关系)。

  5. 用 devtool 查看了下按钮的字体样式,果然继承自 body,这个 body 上设置的字体样式是 lib.flexible 生成的,因为之前调研过一点 lib.flexible 知道其会在 html 上也会设置字体样式,而且 html 的字体是大于按钮行高的。难道是因为 lib.flexible 先设置了 html 上的字体然后再设置 body 上的字体导致这个按钮的字体样式继承关系从 html 变成了 body 导致了动画效果的产生?

  6. 那步骤3的触发条件如何解释呢?注释掉获取某个元素的 offsetHeight 这行代码,页面上的 lib.flexible 并不会产生这个 bug 啊(说明先设置 html 字体,再设置 body 字体,导致的按钮字体样式从继承 html 再继承 body 这一过程不会触发动画)。而且从 js 引用关系来看(先引用的 flexible.js,然后再引用的项目 index.js),获取某个元素的 offsetHeight 导致的 reflow 应该是在 html body 被设置完字体样式后啊?根据已有线索:一、reflow 触发此次 bug,二、元素字体样式继承关系从 html 变成了 body。瞬间猜测设置 html 和 body 字体样式的代码可能是异步的,而 reflow 就发生在他们两步中间。遂去查看 lib.flexible 源码,果然设置 body 的代码是异步的:

doc.addEventListener('DOMContentLoaded', function(e) {
    doc.body.style.fontSize = 12 * dpr + 'px';
}, false);

那基本就定下来产生这个 bug 是因为先设置了 html 的字体,然后获取某个元素 offsetHeight 这行代码产生的 reflow 导致按钮字体样式生效(继承自 html 字体),最后设置 body 字体样式导致按钮字体样式又变成了 body 的字体(继承优先级被 body 覆盖),按钮字体样式的变化导致行高变化触发了动画效果。

  1. 那为什么没有那行导致 reflow 的代码就不会产生这个 bug 呢?我自己依稀记得浏览器并不会在 js 每次修改样式时都及时去让修改生效,而会合并某些修改。遂想 google 这方面的内容,但是短时间内没有查到细节,只查到了:

浏览器不会在每一次样式变化后就去重新relfow一次,一般来说,浏览器会把这样的操作积攒一批,然后做一次reflow,这又叫异步reflow或增量异步reflow。但是有些时候,我们的脚本会阻止浏览器这么干,比如:如果我们请求下面的一些DOM值:offsetTop, offsetLeft, offsetWidth, offsetHeight。

所以此次 debug 顺利找到了产生 bug 的原因,此过程中产生了两个待调研的新知识点:一、字体和行高的关系。二、浏览器如何优化 js 对样式的修改。

回溯下整个 debug 过程,步骤1,2是项目经验起了作用(如何凭借第六感去定位问题,遇到类似现象以前是如何定位问题的),步骤3,5,6,7是基础知识起了作用(步骤3 - reflow 知识,步骤5 - css 样式继承知识,步骤6 - js 异步原理,步骤7 - 笼统的浏览器绘制原理)。而此次 debug 花费时间最长的是步骤4,也就是我 css 基础知识盲点导致的。所以经验可以积累,但基础知识还得靠我们程序员自己花力气去学习及完善

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

推荐阅读更多精彩内容