[ExtJS] viewModel 你所不知道的坑(一)緩存

之前在一些文章都介紹過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的值,就會出現如下錯誤

+

所以,自己動手,豐衣足食

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章