第一期:前端九条bug分享

分享bug的目的

开发过程当中bug常相伴, 不能修复或者没法复现就忽略这些问题, 因此计划每当我遇到9个有价值有思考的bug就会统一分享出来, 以此来扩展性的思考工做自己, 不断的提升本身的意识, 毕竟能力的提升遇到的bug必定不一样, 并且若是遇到bug愈来愈少只能说明本身的工做任务与学习任务在'原地踏步,且不饱和', 既然如此就靠bug来见证本身的成长吧.css

1: element-ui: el-card标签

bug现象:
有一天测试忽然跟我说, 一个当前版本根本没动过的页面发生bug, 页面有些数据为空, 有些按钮点击无效.
bug追查:
第一分析: 那好吧根本没动过的页面出问题那就是历史遗留问题或者后端返回出了问题, 那就去排查一番吧,可是排查的过程令我傻眼, 后台返回了值可是莫名其妙的一直在报'空值'的错, 并且这是一个三年的老项目仍是其余项目组转过来了, 说实话代码很烂很乱, 使用了大量的mixin还有部分逻辑进入了node_modules里面尚未文档, 这个时候只能暴力破解了, 打个debugger一步一步的追查下去, 真的定位了好久发现了关键点, 是某个子组件没有获得传值, 而后这个子组件还会往父组件传一个值, 这才致使了父组件里面的某些值为空从而报错, 看了看向线上的项目没有这些问题, 这有我这个版本有问题那么必定是有人动了这一页的代码, 或者总体环境的某个全局属性被篡改了那问题涉及就广了, 调出gitlab当前页的上一个版本代码,(这里是一个小技巧)把当前代码commit, 生成缓存而后把上个版本的代码覆盖当前代码, 在deff里面就能够看到两版本代码的差别了, 我发现本来根标签是<div>...</div>, 而此次的是<el-card></el-card>, 思惟有点堵塞:就换了个标签而已, 不涉及任何的属性与变量, 怎么可能致使数据崩溃??
bug缘由:
罪魁祸首是这个this.$parent, 原来上一个同窗在组件里面是经过父级组件的实例来获取父级传过来的数据的, 那么问题明了了<el-card></el-card>标签成为了他的父级, 那么它理所固然的取不到更上一级的数据了, 因此获取到的数据就是空的,'凶手'就是它.
bug解决:html

  1. this.$parent为'行间传值'的形式, 并测试是否好用.
  2. 寻找全局是否还有相似的状况, 一一改正.
  3. 找到添加<el-card>的同窗, 说明缘由, 以及询问他是否还如此改变过其余地方的代码, 放弃其余工程也出现类型的状况.

bug思考:
this.$parent 或者是 this.$children这种方式获取与传递数据十分不妥, 由于没有明确数据来源与使用者, 这样就会致使除了问题很难排查, 这种"父与子"的关系很脆弱,很容易忽然'父组件'变成爷爷组件了, bug也就随之而来, 因此不是不得已的状况下或是高度封装的环境下, 不推荐使用.
随意的改变一块代码, 你的知识范围里面感受没有影响,但不表明就真的没有影响, 不要忽视"验证"这个环节, 本身写的代码本身须要负责任ok?前端

2: antv: 折线图倒叙

bug现象:
以前使用公司二次封装的echarts开发, 这个版本使用了antv来开发图表, 可是怪异的事情出现了, 折线图的'y轴'出现了倒叙的现象, 也就是 10, 5, 0 这种怪异的排列, 致使图表上下颠倒.
bug追查:
以前没有相似问题, 这个版本才出现, 这个版本后端没有动接口, 那么问题就在这个组件的使用上, 第一分析: 是否有这样一个属性, 控制了y轴的正反? 去看文档没有找到, 第二分析: 去看官网的实例, 一个字母都不差的拷贝过来但仍是反的, 第三分析: 那么问题出在数据上, 可是数据没有变换, 那么问题出在两套插件处理数据的机制上, 仔细观察再仔细观察, 发现了!原来后台返回的数字是'字符串类型的'.
bug缘由:
原来antv只会对'number'进行从小到大的排序, 汉字的话就按接收顺序显示了, 我把组数据都+一下就ok了
bug思考:
不一样组件库对数据的处理形式也是不一样的, 不要觉得换了个组件库知识变更api的方法就能够了, 还会有不少'原罪'.
经过使用三套不一样的图表库, 使我受益不浅, 并非图表绚丽的效果, 而是对每种图表调用方式的思考, 让我更深刻的理解设计模式.vue

3: 正则: 前瞻性匹配vs火狐

bug现象: node

项目忽然没法在火狐,ie浏览器上运行,固然项目只须要在谷歌浏览器运行, 可是这个现象我仍是想探究一下.
bug追查:
本次排查顺序不太对, 我先看上个版本是否均可以在火狐运行, 发现上个版本没问题那就把问题定位在当前版本, 其实应该先看控制台报错, 可是因为页面是空白的理所固然的认为彻底崩溃了, 或者是后台返回错了, (下次必定先追查控制台的报错信息) 也就是这一段"SyntaxError: invalid regexp group", 是前瞻性匹配出了问题, 我在为数值加千分号的过滤器上使用了以下的代码, (其实我本身写的是翻转字符串逢3位加',')git

export default {
  install(vm) { // 若是后面是3的倍数,那么就加一个','
    vm.filter('formatThousand', (num) => {
      if (!num) return 0;
      const reg = /\d{1,3}(?=(\d{3})+$)/g;
      return (`${num}`).replace(reg, '$&,');
    });
  },
};

那么注释掉这个代码就不报错了么?答案是否认的, 报错仍然在继续, 我打开vscode的搜索台, 输入了前瞻性匹配的语法, 可是啥也搜不到, 思考....vscode搜索台也是有局限的, 好比他不会深刻到node_modules里面查找, 这样也是为了性能, 那么必定是此次新引入的插件除了问题, 通过查找果真是由于咱们本身公司制做的'3d视图'组件使用了正则的前瞻匹配, 可是为了更好的推动公司技术的发展还必须使用公司的技术, 那么如今不是抱怨而是反馈, 把这个问题与可视化部门明确, 还好当前项目本就不用刻意兼容火狐可是其余项目要注意喽.
啥是前瞻性匹配:
正则是js基础, 若是不熟练的同窗须要检讨了,?还能够解除贪婪模式
(?=exp)匹配后面知足表达式exp的位置
(?!exp)匹配后面不知足表达式exp的位置
bug缘由:
原来ie与火狐浏览器并不支持前瞻性匹配web

bug思考:
不少时候咱们会忽略某些方法的兼容性, 甚至某些插件没有照顾兼容性, 那么选技术的时候必定要根据项目要求而定. 如果咱们本身开发插件也要写好兼容范围方便你们使用.npm

4: scss: 引入scss文件无效

bug现象:
须要全局改变table相关的样式, 我单独抽出了个scss文件放在最外层, 可是怪异的事情发生了, scss文件里面的嵌套写法不生效, 必需要拿出来像css文件同样的写法才生效
bug追查:
定位问题:嵌套的写法无效, 那么变量是否有效?答案是也无效, 那就是说我引入了scss文件没问题, 系统也解析, 可是scss的写法系统不认识, 那么难道是个人scss-loader坏了?? 每一个vue文件里面写上lang='scss'都是没问题的, 那么找以前的工程的引入方式复制粘贴,仍是不行....
bug缘由:
css的引入两种方式, 有一种是scss提供的以下:
使用第二种方式能够正确的解析scss文件element-ui

@import url('./assets/style/animation.css'); // css提供的
@import '@/assets/style/animation.scss'; // scss提供的

bug思考:
不要小瞧引入方式.
编写项目css是很是重要的一部分, 主要有'ben'与'oocss'两种思想,有的人直接把css写在html文件里面, 也有人直接写在 app.vue文件里面不加'scoped'就是全局的模式了, 这些固然都没问题,可是毕竟咱们是有追求的工程师, 要作到'美观'与'工程化', '色香味俱全'才是好的代码.后端

5: vue: 文件夹不要叫bin

bug现象:
我上一篇文章里面分享了如何在项目里面作mock的工程化, 可是吧mock工程放入某些工程以后出现了怪异的错误, 首先能够正常启动, 8080端口也启动成功, 可是...浏览器访问的一瞬间就会终止localhost的服务, 强制退出可还行??
bug追查:
说实话第一时间脑海空白, 具体的缘由想不通, 反复试验了几回以后肯定了bug的具体现象, 在每一个操做处打debugger, 仍然追查不到缘由, 可是报错都是在bin这个文件夹里面, 里面的文件也都没问题正常的执行, 那么会不会是这个bin文件夹自己有问题, 改个名字试试? 还真就行了~~
bug缘由:
bin这个文件名比较特殊, 改为其余的马上就行了
bug思考:
不要轻易使用系统经常使用文件名, 以前有一次写我本身的ccpack也是js的index文件与node环境的index文件冲突, 不能够都叫index...., 起名也要谨慎啊.

6: token: 储存在哪里比较好?

bug现象:
咱们的token一直都是存在cookie里面, 但是最近在深刻学习web安全相关知识, 感受这样并不必定对.
bug缘由:
csrf攻击以下: 你在a网站登陆成功, b是钓鱼网站, 你点击b的时候会向a网站发送请求冒充你本人的请求, 这个时候浏览器会默认带上你在a网站登陆的cookie信息发送过去, 而这个请求不光利用img标签进行get请求, 还能够利用form表单进行post请求, 因此这个token不能放在cookie这种位置吧, 并且还不是httponly, 更合理的是放在local storage里面, 每次请求附加在header上面, 而且随时准备更新它,这样csrf的时候是取不到local storage的值的.
bug问题反馈:
与相关同窗交流了这个问题, 由于在cookie加上token是后端直接操做的, 可是因为这个问题后端同窗已经封装在统一的中间件里面, 要是修改的话涉及面有一些广, 可是其余的方式能够起到补救的效果, 好比验证referer 来源信息, 白名单, 二次验证等等.
在这个问题上获得的启示是, 不少核心的逻辑不能够草草就制定, 并且能作到更好为何不作那?

7: pm2: restart并不靠谱

bug原由:
如今服务端渲染的项目也很多, 前端工程师大部分都是使用node来作的, 线程保护方面大部分也是选用pm2, 毕竟pm2简洁明了还自带'负载均衡'
bug现象:
在本地与test环境都没问题, 上线的晚上我执行了如下操做

sudo -s
cd /home/xxxx/xxxx/  // 线上环境目录
git pull 
npm run build
pm2 restart all

可是奇怪的事情发生了, 启动的时候都是'成功', 过了2秒钟, 其中四个server变成了error, (为何是4个server, 由于分配了四核)我从新build项目, 再次pm2 restart all 仍然无效, bug来了开始本该兴奋, 可是奈何正在上线项目你们都很急,那就须要紧张起来了, 先看onerror日志由于在服务器环境因此只能cat看, 可是日志一团乱麻看了一会没有找到真正的缘由, 难道是build出了大问题?test是好的啊, 当时陷入了反复build与restart的傻操做, 冷静一下和这个问题有没有可能不是打包错误而是服务错误? 问题不在咱们的代码而是在pm2自己出现了冲突之类的, 那好假设'restart重启'不能解决问题, 那我直接 pm2 delete id 这样删除掉4个server, 而后 pm2 start ./server.js -i 4 从新启动还真就ok了.

bug分析:
遇到事情从本身身上找缘由是好的品质, 可是不能够只局限在怀疑本身, 也要考虑也许是其余技术出了问题.
pm2也只是个系统, 偶尔不是重启他监控的项目而是重启它自己.

8: vue: $变量的用处

bug原由:
公司的3d技术团队开发的一套组件, 在接收实例的时候命名必须是'$a'不能够是'a'.
请教了可视化团队的同窗, 得知$与_开头的变量不会被vue监控, 这样这个变量咱们能够本身来监控, 更加的灵活.
使用$:
在data里面定义$txt变量而且在行间<span>{{$txt}}</span>报错以下:

`Property "$txt" must be accessed with "$data.$txt" because properties starting with "$" or "_" are not proxied in the Vue instance to prevent conflicts with Vue internals.`

必须使用“$data.$txt”访问属性'$txt',由于在Vue实例中不代理以 "$" or "_"开头的属性,以防止与Vue内部发生冲突。

使用_:
在data里面定义_txt变量而且在行间<span>{{_txt}}</span>报错以下:

`Keys starting with with '_' are reserved`

以'_'开头的键被保留

学习'bug':

data(){
    return {
      $txt:{},
    }
  },
  created(){
    this.$txt = {n:2};
  },
  mounted(){
    console.log(this.$txt) // {n:2}  可是, span标签里面的值不会变
  }

咱们来对他进行监控

created() {
    this.$txt = { n: 2 };
    let n = 2;
    Object.defineProperty(this.$txt, "n", {
      get() {
        return n;
      },
      set(val) {
        return (n = val);
      }
    });
  },
  mounted() {
    this.$txt.n = 3;
    console.log(this.$txt.n); // 3
  }

这样就实现了: 数据挂在data上面能够取到, 可是这个数据又没有vue进行监控, 这样玩法就多了去了, 是个挺不错的思惟.
解释
由于我用'a'接值会致使vue的观察与3d团队的观察冲突, 因此报错'$a'固然就不冲突了
反馈
这个技术点我已于3d团队进行反馈, 但愿在文档中明确, 防止其余同窗挠头.

9: dom: ResizeObserver

bug显现:
在使用可视化团队开发的图标组件时发现了问题, 当窗口size变化的时候, 图标会自动调整本身的布局宽度, 可是...这个图标是100%充满父级的, 或者是flex:1充满父级的, 当他的父级变化,并无出发winodw.onresize的事件的时候, 突变没有调整本身的宽度.
bug原由:
只监控了窗口的尺寸变化, 忽略了父级自己的尺寸变化
bug解决方案1:
我对可使其父级宽度变化的function加上了一个cb, 这样就知道父级的每次更改了, 可是这个须要在能影响父级变化的函数里面逐一的加.
bug解决方案2: 限谷歌
神奇的ResizeObserver, 简直好用

<template>
  <div>
    <div ref="wrap" class="wrap">
      <div class="box">1</div>
    </div>
  </div>
</template>

<script>
export default {
 mounted(){
   const wrap = this.$refs.wrap;
   // 建立监控实例
   const resizeObserver = new ResizeObserver((item)=>{
     console.log('变化', item) // item是数组, 变化者们
   });
   // 投入被观察者dom
   resizeObserver.observe(wrap)
   // 固然能够解除观察, 性能不用太担忧
   // resizeObserver.unobserve(wrap);
 }
}
</script>

<style>
 .wrap{
   border: 1px solid red;
   width: 50%;
 }
 .box{
   border: 1px solid black;
   margin: 20px;
 }
</style>

end: 感谢观看, 欢迎交流, 祝天天进步

相关文章
相关标签/搜索