`审核人:孙雨珩`
`被审核代码负责人:欧阳德才`
`代码地址: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-谢洋