第一期:前端九條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: 感謝觀看, 歡迎交流, 祝天天進步

相關文章
相關標籤/搜索