基礎設施文件應保持小巧,尤爲是類庫與框架,文件體積上及代碼設計上應儘量的最優css
通用組件只提供核心功能,其它個性功能在各個項目中進行定製html
當須要使用社區類庫或組件時,除基礎類庫外,我建議只把用到的功能拿過來,好比underscore,只用了數組操做?把數組操做拿過來。有空多讀讀源碼,嘗試把這些優秀的類庫再作一些拆分,你會發現你經常使用的功能也不過就那幾個,其它不少功能根本用不到。前端
常常去review
代碼,尤爲是複雜數據的處理,好比部分項目中有這樣的代碼git
_.each(campaignModelData.mediaType, function(item) { _.each(mediaTypeList, function(_item) { if (_item.id == item) { _item.checked = true } }) }) _.each(campaignModelData.terminalType, function(item) { _.each(terminalTypeList, function(_item) { if (_item.id == item) { _item.checked = true } }) }) _.each(campaignModelData.shopId, function(item) { _.each(shopIds, function(_item) { if (_item.id == item) { _item.checked = true } }) })
且不論`_.each vs for`的性能,看這3對嵌套的each,咱們只分析第1對的each,後面2個同理github
第1對就是若是mediaTypeList
數組元素在mediaType
元素中,則標識checked
爲true
數組
假設medaiTypeList的長度爲10,medaiType長度也爲10 則第1對each跑完須要100次
若是咱們對代碼改造一下成:瀏覽器
var map={}; _.each(campaignModelData.mediaType, function(item) { map[item]=1; }); _.each(mediaTypeList, function(_item) { if (map[_item.id] == 1) { _item.checked = true } })
減小嵌套,則這時候bash
假設medaiTypeList的長度爲10,medaiType長度也爲10 則each跑完須要20次
咱們能夠明顯減小CPU的計算。數據結構
再好比這段代碼框架
//得到不熱門的定向數據,並提示 _.each(data.list, function(item) { var videos = item.unSellVideoTheme var videoArr = [] var videoStr = '' var length = 0 _.each(videos, function(video) { if (video.unSellVideoTags.length) { length++ _.each(video.unSellVideoTags, function(tag) { _.each(tag, function(name, id) { videoArr.push(name) }) }) } }) })
咱們能夠看到是4個each嵌套,一樣,若是每一個數組有10個元素,則跑完這些循環須要10000次
再如這段
_.each(result, function(algoItem) { _.each(data.campaignTransList, function(item) { _.each(item.targetList, function(targetItem) { if (targetItem.id == algoItem.id) { targetItem.suggestPrice = algoItem.bidPrice } }) }) })
像這樣的代碼在不少項目中都有,而事實上項目中數組的數據要大於我舉例中的10個,因此真實循環中可能幾千、幾萬、幾十萬次都是有可能的。
有些循環是能夠經過前面相似打平,不去嵌套的方式實現,而有些是很難這樣作的,這時候可能須要咱們變換或從新設計數據結構,從而減小數據循環查找的可能。
還有一些菜單數據的處理
case 2 : menus = [ ms.source._cs([ ms.media_2._cs([ ms.media, ms.adzone ]) ]) ]; break;
與其根據權限動態的拼湊出菜單,不如在設計菜單時這樣設計
var ms = { "promotion" : { name : "推廣管理" , url : "/activity/index",children:['activity'],permission:'1'}, "activity" : {name:"活動管理" , url : "/activity/index", icon: ""} ]
咱們能夠經過設計合理的數據結構,減小一些循環的處理。
相似這樣的css選擇器 .form-div .line-detail .line-resolution .dropdown-toggle
在咱們項目中仍是比較常見的,咱們這之因此嵌套這麼多就是把樣式限定在特定的範圍內,但這樣作也給瀏覽器解析帶來必定的壓力。
樣式問題咱們能夠經過 css模塊 相似這樣的方案來解決,讓工具幫咱們處理。
樣式能夠出一個選擇器檢查工具,避免嵌套過深的選擇器
把線上一些固定計算轉移到線下來作。
若是咱們作一個拖動排序或拖動到的功能,像郵件能夠從收件箱拖到垃圾箱,常見的方案都是計算目標節點的位置與大小,而後再比較鼠標的位置。這是一個很是通用的,也不多有bug的方案,其它的也有監聽目標節點mouseenter事件的,可是或多或少都有一些問題。監聽drag事件,要看瀏覽器的支持狀況
對於這個場景,其實有一個更高效的document.elementFromPoint方法,在拖動時檢測鼠標下的節點是很是方便的。不管節點多少都不會引發性能問題,並不隨節點的增多致使查找時的性能降低
一樣,magix在設計DOM事件監聽時,1個view有click,仍是1000個view有click,查找性能是同樣的,即便這些view是嵌套存在的。magix並不會把這些事件處理函數放到一個數組中去處理,由於這樣會隨着事件處理函數的增長而致使調用時性能降低。magix針對自身的特色,在事件這塊從新設計:全局一個統一處理函數,無論事件類型,也無論有多少個view有什麼樣的事件,同類型的事件在全局只會向body上綁定一次,而後由全局處理函數統一處理。magix中的事件代理
印象深入的另外一件事是對搜索關鍵字的查詢優化,關鍵字一萬多個一次發送到前端,而後前端根據用戶的輸入過濾出匹配的項。按正常思路咱們在用戶輸入後對整個關鍵字列表進行查詢,而後把匹配的顯示出來。每次輸入都要查詢一萬次,在用戶連續輸入的狀況下就沒法及時的給出反饋。
當時給出的實現的方案是,拿到關鍵字列表後,作一個字典樹,當用戶輸入變化時,沿着字典樹向下查找,每次並不會遍歷一萬屢次,即便用戶在快速連續輸入的狀況下也能及時響應。
如今的硬件很好,速度很快,向上面我提的這些點不去改進項目也跑的很好。而有一些點咱們直接去測試時,幾乎沒什麼差異,好比循環100次和循環10萬次,也就1ms的差異。那麼咱們是否應該去優化?
性能的問題是一個習慣的問題,咱們平時若是看到了更優的解法,承認這種解法,就應該改變本身原有的習慣,而後把應用這種更優解法變成你的習慣。
無論當前硬件多強大,一臺計算機的能力老是有限的,而你也沒法預知你正在開發的應用未來會變得多龐大,也不會知道什麼時間會出現性能瓶頸。性能的事情也是點滴的事情,你的頁面不會由於多了1萬次循環變得卡頓,也不會由於你減小了1萬次循環變得異常流暢。一旦你的頁面出現了卡頓,想再回頭優化到流暢一般是很難的。
先作功能,回頭再優化性能是不對的,性能的事情要在寫代碼前就已經解決的。
讓本來很快、很流暢的應用變得更快更流暢很差麼?