《layui中table組件內存佔用不斷上升問題》在這篇文章中提到了table組件內存佔用問題。今天給出自己的優化方式。那篇文章已經提到了問題的核心。重複調用render()方法,該方法是一個全過程方法,包括配置的解析處理,組件的框架渲染,各組成部分的渲染,數據的填充等等。在重複調用時,大量的中間數據、對象沒有及時釋放導致內存一直上升。實際應用中是完全不需要每次全過程的構建。只需要重新獲取數據,更新部分相關ui部分,如:頁碼,記錄總數等等。
查看源碼,可以看到獲取數據有單獨的方法:pullData。那麼在執行頁面查詢、及刷新時,只需要調用該方法即可。
在table模塊中增加如下接口:
//表格加載
table.query=function(id,param){
var config = getThisTableConfig(id); //獲取當前實例配置項
if(!config) return;
var that = thisTable.that[id];
that.config = $.extend(true, {}, that.config, {where:param});
that.page=1;
that.pullData(that.page);
};
//表格刷新
table.refresh=function(id){
var config = getThisTableConfig(id); //獲取當前實例配置項
if(!config) return;
var that = thisTable.that[id];
that.pullData(that.page);
};
兩者的區別就是,查詢需要傳入新的查詢條件,同時將頁面設置爲1;而刷新不需要設置任何東西,只是單純的重新獲取一次數據。
第二點說下table表格的編輯功能。設置了編輯功能後,就可以直接在table中的單元格中編輯數據。並且原組件提供了一個編輯過程中的事件:單元格編輯時的change事件。這是一個內部事件處理。在這處理過程中對外提供了一個接口 edit(filter) 可以讓用戶進行再處理。但在 edit(filter)調用前,已經將輸入值設置到內部數據對象了。即這個對外接口已經無法影響編輯值了。而實際應用中更合理的情況是,在外部接口中會對數據進行校驗,根據校驗結果來決定是否將編輯值寫入內部數據對象。說到校驗好像table的編輯功能還沒有校驗功能。需要自己增強該功能。
既然要加校驗,一般情況是編輯完了,再進行校驗,校驗通過了,新值才能寫入內部數據對象同時界面也顯示新值。有些情況下可以邊輸入值邊校驗,如只能輸入整數。非整數可以即時校驗及時清除。但有些則不行,如小數。輸入小數點的時候,應該是合法的,可如果輸入了小數點後就不再輸入。有不是一個有效數字。這是即時校驗不好處理的。所以還不如統一放在輸入完成後進行校驗。也就是blur事件中。
原組件有blur事件處理,是內部處理。沒有對外提供接口。因此可以把change事件中的對外接口關閉,在blur中增加對外接口。
//單元格編輯
that.layBody.on('input', '.'+ELEM_EDIT, function(){ //change
var othis = $(this)
,value = this.value
,field = othis.parent().data('field')
,key=othis.parent().data('key')
,col=that.getColsConfig(parseInt((key.split('-'))[2]))
,index = othis.parents('tr').eq(0).data('index')
,data = table.cache[that.key][index];
//data[field] = value; //更新緩存中的值
var callRtn=layui.event.call(this, MOD_NAME, 'edit('+ filter +')', commonMember.call(this, {
value: value
,field: field
,col:col
}));
}).on('blur', '.'+ELEM_EDIT, function(){
var templet
,othis = $(this)
,value = this.value
,thisElem = this
,field = othis.parent().data('field')
,key=othis.parent().data('key')
,col=that.getColsConfig(parseInt((key.split('-'))[2]))
,index = othis.parents('tr').eq(0).data('index')
,data = table.cache[that.key][index];
//add 2020.4.10
var callRtn=layui.event.call(this, MOD_NAME, 'afterEdit('+ filter +')', commonMember.call(this, {
value: value
,field: field
,col:col
}));
if(callRtn!=null&&callRtn==false){
return;
}
data[field] = value; //更新緩存中的值
afterEdit就是我們新增加的對外接口,原edit對外接口沒有關閉先留着。同時數據對象的更新也是放在afterEdit之後。且是根據對外接口的結果值來控制的。這爲校驗提供了條件。
還差一個條件。校驗需要校驗規則。校驗規則如何配置?很自然配置在列配置對象中好理解。
width:150,align:'right',edit:'text',error:'應爲整數',dataType:'Number'},
列配置是組件的入口,是一個很好的擴展點。
現在需要回調接口:afterEdit中來獲取校驗規則。原組件在調用回調方法時,主要傳入當前編輯數據,tr對象之類。沒有列配置對象。所以這是一個需要我們修改的地方
,col=that.getColsConfig(parseInt((key.split('-'))[2]))
var callRtn=layui.event.call(this, MOD_NAME, 'afterEdit('+ filter +')', commonMember.call(this, {
value: value
,field: field
,col:col
}));
在到回調方法中應用規則
table.on('afterEdit(tab-car-run)', function(obj){
var col=obj.col
,tr=obj.tr
,td=$(tr).find("td[data-field='"+obj.field+"']");
var rst=validator.validate(obj.value,col.require,col.dataType);
if(!rst){
layer.tips(col.error||'數據格式不正確', td,{tips: 3});
}
return rst;
});
還有一個增強的地方:編輯按數據後,需要知道哪些行的數據是被編輯過。這樣做保存數據到後臺時,更方便。而不是將所有數據都覆蓋式的保存。
還有其他組件也有優化和增強的地方,以後細說。感覺這套組件缺乏實際項目的錘鍊。簡單應用可能沒什麼問題,大點的應用要有采坑的準備和填坑的能力