盤點前端問題,你知道幾個?
在回家的路上,一直在思考需求的可行性,索性把最近的已知的問題做一個簡單的復盤。
在網(wǎng)上也看了很多bug匯總,都寫的比較細,那么我們是否可以宏觀的思考,為什么會造成錯誤。
簡單的歸納了幾個點:
- 代碼邏輯錯誤
- 產(chǎn)品需求錯誤
- 場景缺失錯誤
- 異步錯誤
- 概念理解錯誤
接下來展開討論一下。
代碼邏輯錯誤
「 人很容易發(fā)現(xiàn)別人的錯誤,而對自己的錯誤視而不見 」
要想發(fā)現(xiàn)代碼邏輯的問題,最簡單的辦法就是看老代碼或者看別人的代碼。代碼邏輯體現(xiàn)的是你對需求的理解,以及你對整個產(chǎn)品邏輯的把控。
比如一個列表的渲染。每一次請求我們都會標記返回的數(shù)據(jù)列表,記作now_list,然后把列表拼接到現(xiàn)有的列表上面,記作list。當列表底部到頁面底部的距離大于一定數(shù)值的時候會自動觸發(fā)請求,加載loading。然后判斷當now_list為空的時候,停止自動觸發(fā)。這是正常的邏輯。
接下來,騷操作來了,把loading的開啟條件放在了觸發(fā)條件里,我們可以記作這個觸發(fā)的方法為onEndReached,把關閉loading的方法放在了請求方法里。這樣導致的結(jié)果就是當起始數(shù)據(jù)量小(比如列表長度為1的時候)的情況下,會不斷觸發(fā)loading,關閉loading,然后進入死循環(huán)。然后又一個騷操作來了,因為每次請求的列表數(shù)量為4,所以在onEndReached方法里,添加里一個判斷條件,當now_list的長度小于4的時候,不開啟loading。很簡單的問題繞了一個大圈。而且像這種以數(shù)字為條件的的代碼邏輯,一定要引起警惕。因為這預示著你的代碼邏輯不嚴謹。關于代碼邏輯的問題還有多層判斷條件的問題,比如報告的生成與查看,查看報告的按鈕除了不能在狀態(tài)1和8展示,其余狀態(tài)都可以展示;而下載報告的按鈕只能在狀態(tài)5或6展示,分享報告的按鈕只能在6展示。無論查看、下載、分享都操作的是同一個按鈕。像這種邏輯判斷條件多的情況,極易產(chǎn)生錯誤。
產(chǎn)品需求的錯誤
「 需求評審,都是一場辯論會,不是說服別人就是被說服 」不要太相信產(chǎn)品,因為他們也會犯錯誤。總結(jié)了一下已知產(chǎn)品需求的錯誤,分兩類:
- 無用的需求
- 不合理的需求
先說一下無用的需求,為什么說是無用的,比如上一版做的功能,下一版全部推翻。也就是說,在上一段時間內(nèi),你在做無用功,沒有對產(chǎn)品產(chǎn)生任何價值。一群人白白耗費了一段時間去做了一件毫無意義的事情。再講一下不合理的需求,比如買一贈N,在列表中折疊。不管是贈送的訂單還是正常的訂單,在訂單列表中是平鋪的。為了解決訂單之間的關聯(lián)關系,給用戶呈現(xiàn)層級的展示效果,前端需要做的是把平鋪的數(shù)據(jù)整合成樹狀結(jié)構(gòu),然后折疊起來,方便用戶查看。列表請求數(shù)據(jù)條數(shù)是一定的,比如4條數(shù)據(jù)就可以填滿屏幕,我們一般會請求5條,以便上拉加載。那么我們可以假設一下場景,比如買一贈7,當我們首先加載完5條數(shù)據(jù),并整合成樹狀結(jié)構(gòu),折疊起來就變成了一條數(shù)據(jù),就會再次觸發(fā)請求加載,這次我們又加載了5條,不巧的是下一次的正常訂單也是買一贈7,前3條數(shù)據(jù)還是上一條的贈送單,那么我們繼續(xù)重組數(shù)據(jù),現(xiàn)在訂單中有兩條數(shù)據(jù),第一條數(shù)據(jù)折疊了7條,第二條數(shù)據(jù)折疊了一條,還會繼續(xù)觸發(fā)請求加載,直到屏幕上放滿了正常的訂單。這個過程會不斷的重組數(shù)據(jù),并不斷的加載loading,關閉loading。專業(yè)點的術語可以叫"閃屏"。當然可以把折疊的數(shù)據(jù)默認展開,這也不失為一個好方法。我承認我們做的一些需求不一定合乎規(guī)范,并確實解決了一些問題。但是后期的維護實在太困難,而且不可預料。
場景缺失的錯誤
「 改bug,最忌諱的就是改一處,制造兩處 」
場景缺失的問題,也可以簡單的歸為兩類:
- 同樣問題,只改了一處,其他處沒有考慮到
- 關聯(lián)問題,只改了有問題的地方,后續(xù)產(chǎn)生的問題沒有考慮到
前端時間的地址問題確實困擾了一段時間,側(cè)面反應了處理問題不嚴謹,也反應設計之初沒有考慮周全。
省市區(qū)的問題,會伴隨著傳值、回顯、提交拼接。問題就出現(xiàn)在了拼接。老數(shù)據(jù)是直接拼接在一起的,中間沒有任何特殊標記,而現(xiàn)在的需求是第三方拿到這個數(shù)據(jù)無法解析。舊有的邏輯有自己的一套解析機制,但也存在一定的問題,不嚴謹。所以在已經(jīng)存在問題的基礎修改,注定還是會存在問題。最好的解決辦法就是推翻重新制定規(guī)則。
當我們在解決問題的時候,一定要考慮此處修改的方案是否會對后續(xù)邏輯產(chǎn)生影響,尤其是改別人的代碼邏輯,很多問題預料不到,推翻重寫成本太大,所以在以后寫業(yè)務代碼的時候一定要解耦,堆在一起的代碼,看的實在頭疼。
異步錯誤
代碼執(zhí)行的時機一直以來是一個比較嚴重的問題,比如我們常常發(fā)現(xiàn)的,數(shù)據(jù)已經(jīng)請求到了,為什么頁面沒有顯示。
比如react中的setState,更新DOM樹是一個很耗時的工作,setState會等一個時機做批量的更新,而不是直接更新。
再比如很多同學想在forEach或map中使用async異步函數(shù),但是不要忘了,你接受的結(jié)果也是異步的。
概念理解錯誤
還有一些錯誤的因為你對事物本身不了解。
比如前幾天面試,有一個女孩說「 我剛用vue3寫了一個項目 」,那我就問「 那你vue3常用的語法有哪些 」,她的回答「 vue add、vue ui... 」。我當時腦子就大了。
還有群里哥們問的一個問題:
- ['1','2','3'].map(parseInt)
- // [1, null, null]
- ['1','2','3'].map(Number)
- // [1, 2, 3]
- ['1','2DDDD','3'].map(parseFloat)
- // [1, 2, 3]
問:「 為什么parseInt不可以實現(xiàn)轉(zhuǎn)化 」
map接受方法參數(shù)是固定,只能減少,不能修改,parseInt接受的兩個參數(shù),第二個參數(shù)直接被改成了map規(guī)定的索引值,再執(zhí)行parseInt的邏輯,返回的肯定不對了。
換句簡單的理解就是parseInt接受的參數(shù)被map強行改為了索引:
- parseInt('2',1)
- // NaN
- parseInt('3',2)
- // NaN
本文轉(zhuǎn)載自微信公眾號「驚天碼盜」,可以通過以下二維碼關注。轉(zhuǎn)載本文請聯(lián)系驚天碼盜公眾號。