冬Blog

醉心技术、醉心生活
  博客园  :: 首页  :: 新随笔  :: 订阅 订阅  :: 管理

使用ExtJs开发MIS系统(3):使用数据库保存客户端状态

Posted on 2008-12-19 20:03  冬冬  阅读(5032)  评论(11编辑  收藏  举报

我们都知道,Vs.Net这样的工具每次打开时都会记住我们上次关闭时的状态:各个窗口的位置、大小;工具栏状态;自定义菜单项等。这无疑是一个使用的功能。ExtJs也包含提供了状态保存机制,其主要的控件:GirdPanel,FormPanel等,都提供了状态保存的功能。我们需要的仅仅是为其提供适当的Provider。

1,客户端状态的保存

我们先来看一下当一个ExtJs中的控件状态改变时,持久化该控件状态的流程:

image 

流程中的前两步(红色)是控件负责的。当控件状态改变时,会使用JSON串行化自身状态,然后调用Ext.state.Manager.getProvider()这个静态方法取得当前程序配置的Provider,进而调用Provider的set方法,保存自身状态。我们需要做的便是提供一个Provider,当其set方法被调用时,将传递过来的控件状态保存到服务器就可以了。该Provider的代码如下:

   1:  Srims.providerCtor = Ext.extend(Ext.state.Provider, {
   2:   
   3:      get: function(name, defaultValue){
   4:          //alert('get:' + name + ' : ' + Srims.provider._state[name]);
   5:          //return defaultValue;
   6:          
   7:          if (Srims.provider._state[name]) 
   8:              return Ext.util.JSON.decode(Srims.provider._state[name]);
   9:          
  10:          return defaultValue;
  11:      },
  12:      set: function(name, value){
  13:          //alert('set:' + name + ' ' + Ext.util.JSON.encode(value));
  14:          var valueString = Ext.util.JSON.encode(value)
  15:          Srims.provider._state[name] = valueString;
  16:          
  17:          Ext.Ajax.request({
  18:              url: '/User.asmx/SetExtClientState',
  19:              method: 'POST',
  20:              params: {
  21:                  key: name,
  22:                  value: valueString
  23:              }
  24:          });
  25:      },
  26:      clear: function(name){
  27:          Srims.provider._state[name] = undefined;
  28:      }
  29:  });
  30:   
  31:  Srims.provider = new Srims.providerCtor();
  32:  Srims.provider._state = new function(){
  33:  };

其中Srims.privoider._state(32行)是本地用于保存状态的对象,相当于一个缓存。set方法首先编码控件状态(14行),然后将控件状态储存在Srims.privoider._state中(15行),进而发起Ajax请求,调用WebService,传递控件ID及其状态,服务器端将根据这两个参数持久化该控件当前状态(17行)。至此是流程图中的第三、四两步(蓝色表示)。

定义了Provider类后,我们就可以把它构造出来(31行),然后调用:

Ext.state.Manager.setProvider(Srims.provider);

将我们的Provider设置为系统公用的,这样ExtJs中的控件就可以使用Ext.state.Manager.getProvider()得到这个Provider了。

服务器端Users.asmx的SetExtClientState'方法负责保存客户端控件的状态,对应流程中最后两步(绿色表示)。使用XML串行化所有控件的状态,形成的XML类似以下样子:

   1:  <?xml version="1.0" encoding="utf-8"?>
   2:  <ExtClientState>
   3:    
   4:    <ProjectGridPanel_HorizontalList>
   5:      {"columns":[{"id" :0,"hidden":true},{"id":1,"width":93},......
   6:    </ProjectGridPanel_HorizontalList>
   7:    
   8:    <ProjectGridPanel_VerticalList>
   9:      {"columns":[{"id":0,"hidden":true},......
  10:    </ProjectGridPanel_VerticalList>
  11:    
  12:    <DivPanelMenu>
  13:      {"collapsed":false}
  14:    </DivPanelMenu>
  15:    
  16:  </ExtClientState>

其中节点名称是客户端控件的ID,节点的值是该控件的状态。上面的XML描述了三个控件的状态,其中前两个:ProjectGridPanel_HorizontalListProjectGridPanel_VerticalList是GridPanel,最后一个DivPanelMenu是Panel。

2,状态的加载与还原

当下一次系统加载的时候,我们在所有控件加载之前,先把这个XML发送给客户端,就可以复原客户端状态了,代码如下:

   1:  Srims.provider.loadState = function(callback){
   2:      Ext.Ajax.request({
   3:          url: '/User.asmx/GetExtClientState',
   4:          method: 'POST',
   5:          success: Srims.provider._onLoadState,
   6:          scope: callback
   7:      });
   8:  };
   9:  Srims.provider._onLoadState = function(response){
  10:   
  11:      var rootNode = Ext.DomQuery.selectNode('/ExtClientState', response.responseXML);
  12:      var nodes = Ext.DomQuery.select('*', rootNode);
  13:      
  14:      for (var i = 0; i < nodes.length; i++) {
  15:          var node = nodes[i];
  16:          Srims.provider._state[node.tagName] = Ext.DomQuery.selectValue('/', node);
  17:          //alert(node.tagName + Srims.provider._state[node.tagName]);
  18:      }
  19:      
  20:      this();
  21:  }

第二行的Ajax请求负责从User.asmx/GetExtClientState读客户端状态,其响应是上面的XML。然后回调函数Srims.provider._onLoadState负责将状态解析还原到Srims.provider._state这个本地缓存中。

客户端状态还原后,控件加载的时候,就可以使用Provider提取上次的状态。状态的加载和恢复的流程总结如下:

image 

本文中出现的代码,去掉注释后结合FireBug可以清楚地了解到整个状态保存和还原的过程。