之前在一些文章都介紹過viewModel,一個頁面狀態控制機
、 [ExtJS] viewModel綁定監聽方法 控件動態綁定方法、 [ExtJS]全局viewModel教程
有了它後,我們可以很方便地控制頁面控件的隱藏顯示,信息展示等。
但是,對於viewModel在深究一下,會發現一些問題:
viewModel機制
一般我們會在一個父類 或 同類中設置一個viewModel
{
viewModel:{
data:{
key:value//key value形式設置值
}
}
}
然後,控件通過bind的方式 進行綁定viewModel裏的key
{
xtype:'控件別名',
bind:{
控件具有bindalbe的屬性:'{key}'//或使用 '{key!='aa'}'等運算式
}
}
當ExtJS進行渲染時,只要是有控件使用bind,且bind的key在某層 viewModel內,在viewModel對象就會生成一個bingding對象
看下官網對此的解釋:
聲明性的綁定到此控制器的getViewModel的集合。鍵應該是方法,值應該是bind語句
翻譯一下:
bind對象 生成bingdings 然後 放到了 離控件最近的 viewModel中 (viewModel是可以從父級繼承的,所以自己沒有就會找父輩的viewModel 參見ExtJS viewModel 向下傳遞)
bindings對象裏有個重要參數:scope 作用域
就是此作用域限制了某個bind的應用對象,打開scope 可以看到是控件的構造器對象
一般會在控件對象進行銷燬時,此binding對象也會銷燬.
But 動態設置bind時。。。
這時你就會發現問題來了,比如我們在實例一個控件時 聲明瞭下hidden屬性的bind
{
xtype:'button',
text:'按鈕',
bind:{
hidden:'{status=='edit'}'
}
}
然後我們 拿到這個button對象,對其設置
button對象.setBind(
{
hidden:'{status=="add"}'
}
)
一般在進行setBind時,Extjs 會幫其回收之前的binding對象。
但是更新幾次後,就能看到在viewModel對象中 有了殘留,也就是說上次的綁定狀態值沒有被回收——這就引發一個後果,等再次變更viewModel中的值時,發現控件bind的值與其不匹配了。
例子:
{
xtype:'container',
viewModel:{
data:{
status:'add'
}
},
items:[
{
xtype:'label',
bind:{
html:'status值:{status}'
}
},
{
xtype:'button',
text:'改變status',
handler:function(sender) {
var vm = sender.lookupViewModel();
var status = vm.get('status');
vm.set('status',status=='add'?'edit':'add');
}
},
{
xtype:'button',
text:'根據status隱藏',
itemId:'btn2',
bind:{
hidden:'{status=="add"}'
}
},
{
xtype:'button',
text:'切換2Btn的Bind爲add',
handler:function(sender) {
sender.up().down('#btn2').setBind({hidden:'{status=="add"}'})
}
},
{
xtype:'button',
text:'切換2Btn的Bind爲edit',
handler:function(sender) {
sender.up().down('#btn2').setBind({hidden:'{status=="edit"}'})
}
}
]
}
What Can We Do?
自動回收都靠不住了,就只能自己動手了。
let vm = viewModel對象;
for(var k in vm.bindings) {
if(vm.bindings[k].scope._itemId==node.getId())//通過比對scope對象的特徵值進行判斷
vm.onBindDestroy(vm.bindings[k]);//銷燬vm中的緩存
}
控件對象.setBind({hidden:'{status=="edit"}'});
否則,在這個控件多動態設置bind幾次後,若是先把控件銷燬了,此時要是改動viewModel的值,就會出現如下錯誤
+