`審核人:孫雨珩`
`被審核代碼負責人:歐陽德才`
`代碼地址:https://192.168.1.240:8443/svn/repos/jizhen-fe`
# 技偵指揮大屏代碼審查
#### 1、使用jquery的show&hide控制元素是否顯示(已修改)
在調用jquery元素的hide方法時,jquery還需要去獲取元素原始display屬性的值并進行緩存,然后再恢復展示時又要去緩存里獲取原始屬性值再恢復,太耗性能
解決方案:使用一個css class控制元素是否展示
#### 2、d3操作時對于enter下的元素和update下的元素重復進行樣式更新(已修改)
enter后append的元素實際上會加回到update對應的數組下,樣式更新只需要針對update就好
解決方案:
```
var selection = d3.selectAll('xxx').data(data)
// 這里只做新增,不更新樣式
var enterSelection = selection
.enter()
enterSelection.append('xxx')
// 無用的元素直接移除
selection
.exit()
.remove()
// 現在這個selection不僅包含通過selectAll選中的元素,還包含enter進來的元素,統一更新即可
selection
```
#### 3、right.js的drawLiquidFillGauge方法創建了一個無用的對象(已修改)
在方法末尾創建了一個GaugeUpdater對象,每一個這個對象每次還會創建一個帶閉包的函數,但最后根本沒有使用
解決方案:
確認確實沒有用后將創建GaugeUpdater對象的邏輯刪除
#### 4. 在調用map.js的drawSymbol函數時,在一定入參下會創建一個無法結束的定時任務(已修改)
當入參isSmallMap為真值時,會在函數末尾創建一個無法結束的定時任務,當這個函數被重復調用時會出現更多的定時任務
解決方案:
```
function draw() {
var cancelled = false
setTimeout(function job () {
// 定時任務邏輯寫在這里
if (cancelled) {
return
}
setTimeout(job, 1000)
}, 1000)
return {
cancel: function () {
cancelled = false
}
}
}
```
#### 5.在map.js的drawSymbol函數中,創建了三層嵌套的setTimeout(已修改)
解決方案:
第一層回調函數可以省略,直接根據transitionItems的長度判斷是否要創建第二層setTimeout
#### 6.在map.js的drawSymbol函數中,使用了arguments.callee
arguments的.callee已經被廢棄,不允許使用
```
function () {
setTimeout(arguments.callee, 2000);
}
```
解決方案:
```
// 不使用匿名函數即可
function job() {
setTimeout(job, 2000);
}
```
#### 7.在調用right.js的drawLiquidFillGauge函數時,會創建一個無法結束的定時任務(已修改)
當這個函數被重復調用時會出現更多的定時任務
解決方案:參照第4點
#### 9.在map.js的initMap函數中,在為區塊綁定事件時創建了無用的匿名函數(已修改)
這創建了一個沒有閉包的匿名函數,并且匿名函數中的寫法還創建了一個閉包
```
xxx.on('mouseout', function() {
mouseOut()
})
```
解決方案:
```
xxx.on('mouseout', mouseOut)
```
#### 10.在map.js的victoryCallback函數中,采用循環數組的方式查找和地區id相匹配的中心點位置(已修改)
如果用來查找id在數組的末尾,相當于整個數組都要循環一遍。而且這里不僅查找小地圖中的中心點,還查找大地圖的中心點,在最壞情況下要循環完兩個數組
```
for (j = 0, length = smallMapCentroids.length; j < length; j++) {
if (smallMapCentroids[j].id == kuaibaoData.areaId) {
kuaibaoData.geoCoord = smallMapCentroids[j].centroid
mapNode = '.small-map'
isSmallMap = true
break
}
}
```
解決方案:中心點信息不用數組管理,而是用一個對象以區域id作為索引
```
var feature = {
id: xxx,
centroids: xxx
}
var smallMapCentroids = {}
smallMapCentroids[feature.id] = feature
// 這樣就不用循環了
var searchId = yyy
var feature = smallMapCentroids[searchId]
```
#### 10.在map.js的victoryCallback函數中,每次都通過jquery元素的.is(':hidden')檢查一個元素是否展示(已修改)
.is(':hidden')底層實現不僅會嘗試通過getComputedStyle查詢元素是否存在display:none的css,還會嘗試檢查元素是否在當前文檔中,影響性能
解決方案:對于元素顯示或隱藏,使用class控制。在檢查元素狀態時,通過檢查元素是否有這個class即可
#### 11.在victoryAnimation.js的drawPoint方法中,使用jQuery查找了容器下的svg,但下面并沒有使用這個元素(已修改)
```
// 這個元素在下面并沒有被使用
var container = $(id).find('svg')
```
解決方案:確認無用后,將查詢語句刪除
#### 12.在victoryAnimation.js的drawPoint方法中,創建了無用函數remove(已修改)
```
{
drawPoint: function () {
// 這個函數沒有被使用
function remove() {
d3.selectAll('.vicoryTooltip').remove()
d3.selectAll('.carouselPoint').remove()
}
}
}
```
解決方案:確認無用后,將函數刪除
#### 13.在victoryAnimation.js中的drawPoint方法中,用d3為新建元素綁定了data(已修改)
**這里使用的data是一個對象,而不是數組。所以可以得到以下結論:**
1. 新建時,創建元素的數量跟數據長度無關,是固定只有一個。不需要根據數據長度增減元素。
2. 更新元素屬性時,因為數據只有一個,對應元素也只有一個。不需要通過數據綁定的方式,為不同數據對應的元素分別更新元素屬性。直接使用data更新元素屬性即可。
所以說,在只有一個數據的情況下,根本不需要綁定data。
這個data本身帶有的數據較多,在渲染完畢就可以丟棄的情況下**不應該綁數據**。
因為如果通過d3的selection.data方法綁定數據后,會在選中的元素上創建__data__屬性來保存這個數據,如果通過這個元素select了后代元素,那么后代元素也會有這個__data__屬性,導致data無法被釋放。
解決方案:
```
function createImage(container) {
// 舉個例子,該函數只在新建時調用,所以直接創建需要的image元素即可
container
.append('image')
.classed('ratate-img', true)
}
```
```
function updateImage(container, data) {
// 更新時,直接修改元素對應屬性
container
.select('.ratate-img')
.attr('xxx', data.yyy)
// 甚至不需要用以下這種寫法
// .attr('xxx', function () { return data.yyy })
}
```
#### 14.在victoryAnimation.js中,暴露了全局變量markData,coor,config,carouselPoint(已修改)
看代碼,作者的意圖主要是在drawPoint時,為相關用于新建元素的函數,以及tooltip函數,提供元素容器和數據。
這些信息應該只保留在drawPoint函數執行過程中,而不是暴露到全局,導致了內存浪費
```
function addPoint() {
// 沒有通過入參,而是使用的全局變量
carouselPoint
markData
}
```
```
function(position, victoryId, isSmallMap, markId) {
// 沒有通過入參,而是使用的全局變量
markData
}
```
解決方案:
在調用對應函數時,將相關數據作為入參傳入即可,并不需要暴露到全局
```
function addPoint(carouselPoint, markData) {
// ...
}
```
```
function(markData, victoryId, isSmallMap) {
// 原函數簽名要求position,實際上就是markData的一個子屬性
// 原函數簽名中的markId在函數執行過程中沒有用到,可以去除
var position = markData.coor
}
```
- 1、執法項目
- 1.1 20170523-張紅橋
- 1.2 20170523-李偉
- 2、運維項目
- 2.1 20170527-歐陽德才
- 2.2 20170613-尹幫會&歐陽德才
- 2.3 20170706-歐陽德才
- 2.4 20170706-尹幫會
- 3、指揮大屏項目
- 3.1 20170712-歐陽德才
- 4、PC端項目
- 4.1 20170516-張紅橋
- 5、萬達項目
- 5.1 20170619-李偉&舒曼
- 5.2 20170623-李偉&舒曼
- 5.3 20170803-李偉(未修改)
- 5.4 20170811-李偉(未修改)
- 6、可視化組件
- 6.1 20170718-張紅橋
- 7、UI組件
- 7.1 20170522-舒曼
- 8、新員工練習項目
- 8.1 20170401-歐陽德才
- 8.2 20170401-舒曼
- 8.3 20170503-舒曼
- 8.4 20170609-劉黎
- 8.5 20170620-劉黎
- 8.6 20170703-謝洋
- 8.7 20170706-孫雨珩
- 8.8 20170706-謝洋
- 8.9 20170711-謝洋
- 8.10 20170724-謝洋
- 8.11 20170908-譚俊
- 8.12 20171026-廖爽
- 8.13 20171027-廖爽
- 8.14 20171027-廖爽
- 8.15 20171031-廖爽
- 8.16 20171103-覃英琪
- 8.17 20171103-01-廖爽
- 8.18 20171103-02-廖爽
- 8.19 20171110-趙家紅
- 8.20 20171110-覃英琪
- 8.21 20171110-02-趙家紅
- 8.22 20171115-01-廖爽
- 8.23 20171127-趙家紅
- 8.24 20171122-李祁
- 8.25 20180528-吳泓江
- 9、資源監控大屏
- 9.1 20170705-舒曼
- 9.2 20170711-舒曼
- 9.3 20170724-舒曼
- 10、CQ指揮艙
- 10.1 20170906-張紅橋&李偉&謝洋
- 11、昆明
- 11.1 20171009-李偉&舒曼
- 12、情報墻
- 12.1 20171025-謝洋
- 13、動態管控
- 14、迪愛斯區縣
- 14.1 20171128-歐陽德才
- 15、貴州塊數據指揮調度平臺
- 16、北京東城區可視化項目
- 16.1 20180425-歐陽德才&謝洋
- 16.2 20180510-謝洋