0

目标是为动态数据集使用缓冲存储。工作流程如下:

  1. 服务器上已经存在一些数据。
  2. 客户端使用缓冲存储和无限网格来处理数据。
  3. 当应用程序运行时,存储正在加载,并且“加载”事件将网格滚动到最后一条消息。
  4. 一些记录被添加到服务器。
  5. 客户端收到推送通知并运行商店重新加载。topic.store.load({addRecords: true});
  6. load 事件运行并尝试再次滚动到最后一条消息但失败:

TypeError: offsetsTo is null e = Ext.fly(offsetsTo.el || offsetsTo, '_internal').getXY();

似乎网格视图没有刷新,也没有显示添加的记录,只有它们所在位置的空白。任何想法如何使网格视图正确刷新?

商店初始化:

Ext.define('orm.data.Store', {
  extend: 'Ext.data.Store',
  requires: ['orm.data.writer.Writer'],
  constructor: function (config) {
    Ext.apply(this, config);
    this.proxy = Ext.merge(this.proxy, {
      type: 'rest',
      batchActions: true,
      reader: {
        type: 'json',
        root: 'rows'
      },
      writer: {
        type: 'orm'
      }
    });
    this.callParent(arguments);
  }
});

Ext.define('akma.chat.model.ChatMessage', {
  extend:'Ext.data.Model',
  fields:[
    { name:'id', type:'int', defaultValue : undefined },
    { name:'createDate', type:'date', dateFormat:'Y-m-d\\TH:i:s', defaultValue : undefined },
    { name:'creator', type:'User', isManyToOne : true, defaultValue : undefined },
    { name:'message', type:'string', defaultValue : undefined },
    { name:'nameFrom', type:'string', defaultValue : undefined },
    { name:'topic', type:'Topic', isManyToOne : true, defaultValue : undefined }
  ],
  idProperty: 'id'
});



Ext.define('akma.chat.store.ChatMessages', {
   extend: 'orm.data.Store',
   requires: ['orm.data.Store'],
   alias: 'store.akma.chat.store.ChatMessages',
   storeId: 'ChatMessages',
   model: 'akma.chat.model.ChatMessage',
   proxy: {
   url:  'http://localhost:8080/chat/services/entities/chatmessage'
  }
});

var store = Ext.create('akma.chat.store.ChatMessages', {
  buffered: true,
  pageSize: 10,
  trailingBufferZone: 5,
  leadingBufferZone: 5,
  purgePageCount: 0,
  scrollToLoadBuffer: 10,
  autoLoad: false,
  sorters: [
    {
      property: 'id',
      direction: 'ASC'
    }
  ]
});

网格初始化:

Ext.define('akma.chat.view.TopicGrid', {
  alias: 'widget.akma.chat.view.TopicGrid',
  extend: 'akma.chat.view.grid.DefaultChatMessageGrid',
  requires: ['akma.chat.Chat', 'akma.UIUtils', 'Ext.grid.plugin.BufferedRenderer'],
  features: [],
  hasPagingBar: false,
  height: 500,
  loadedMsg: 0,
  currentPage: 0,
  oldId: undefined,
  forceFit: true,
  itemId: 'topicGrid',
  selModel: {
    pruneRemoved: false
  },
  multiSelect: true,
  viewConfig: {
    trackOver: false
  },
  plugins: [{
    ptype: 'bufferedrenderer',
    pluginId: 'bufferedrenderer',
    variableRowHeight: true,
    trailingBufferZone: 5,
    leadingBufferZone: 5,
    scrollToLoadBuffer: 10
  }],
  tbar: [{
    text: 'unmask',
    handler: function(){
      this.up('#topicGrid').getView().loadMask.hide();
    }
  }],

  constructor: function (config) {

    this.topicId = config.topicId;
    this.store = akma.chat.Chat.getMessageStoreInstance(this.topicId);
    this.topic = akma.chat.Chat.getTopic(this.topicId);

    var topicPanel = this;

    this.store.on('load', function (store, records) {
      var loadedMsg = store.getTotalCount();
      var pageSize = store.pageSize;
      store.currentPage = Math.ceil(loadedMsg/pageSize);
        if (records && records.length > 0) {
          var newId = records[0].data.id;
          if (topicPanel.oldId) {
            var element;
            for (var i = topicPanel.oldId; i < newId; i++) {
              element = Ext.get(i + '');
              topicPanel.blinkMessage(element);
            }
          }
          topicPanel.oldId = records[records.length-1].data.id;
          var view = topicPanel.getView();
          view.refresh();
          topicPanel.getPlugin('bufferedrenderer').scrollTo(store.getTotalCount()-1);
        }
    });

    this.callParent(arguments);
    this.on('afterrender', function (grid) {
      grid.getStore().load();
    });
    var me = this;
    akma.UIUtils.onPasteArray.push(function (e, it) {
      if(e.clipboardData){
        var items = e.clipboardData.items;
        for (var i = 0; i < items.length; ++i) {
          if (items[i].kind == 'file' && items[i].type.indexOf('image/') !== -1) {
            var blob = items[i].getAsFile();
            akma.chat.Chat.upload(blob, function (event) {
              var response = Ext.JSON.decode(event.target.responseText);
              var fileId = response.rows[0].id;
              me.sendMessage('<img src="/chat/services/file?id=' + fileId + '" />');
            })
          }
        }
      }
    });
    akma.UIUtils.addOnPasteListener();
  },
  sendMessage: function(message){
    if(message){
      var topicGrid = this;
      Ext.Ajax.request({
        method: 'POST',
        url: topicGrid.store.proxy.url,
        params:{
          rows: Ext.encode([{"message":message,"topic":{"id":topicGrid.topicId}}])
        }
      });
    }
  },
  blinkMessage: function (messageElement) {
    if (messageElement) {
      var blinking = setInterval(function () {
        messageElement.removeCls('red');
        messageElement.addCls('yellow');
        setTimeout(function () {
          messageElement.addCls('red');
          messageElement.removeCls('yellow');
        }, 250)

      }, 500);
      setTimeout(function () {
        clearInterval(blinking);
        messageElement.addCls('red');
        messageElement.removeCls('yellow');
      }, this.showInterval ? this.showInterval : 3000)
    }
  },
  columns: [        {
      dataIndex: 'message',
      text: 'Message',
      renderer: function (value, p, record) {
        var firstSpan = "<span id='" + record.data.id + "'>";
        var creator = record.data.creator;
        return Ext.String.format('<div style="white-space:normal !important;">{3}{1} : {0}{4}</div>',
            value,
            creator ? '<span style="color: #' + creator.chatColor + ';">' +     creator.username + '</span>' : 'N/A',
            record.data.id,
            firstSpan,
            '</span>'
        );
      }
    }
  ]
});

upd:似乎问题不在视图中。bufferedrenderer 插件绑定滚动到记录。它运行一个回调函数:

       callback: function(range, start, end) {

            me.renderRange(start, end, true);

            targetRec = store.data.getRange(recordIdx, recordIdx)[0];

......

 store.data.getRange(recordIdx, recordIdx)[0] 

尝试获取商店中的最后一条记录。……

 Ext.Array.push(result, Ext.Array.slice(me.getPage(pageNumber), sliceBegin, sliceEnd));

getPage 返回给定页面的所有记录,但缺少最后一条记录,即商店没有完美更新。

任何想法如何解决?

4

2 回答 2

4

问题是 store.load() 没有用新数据填满 store PageMap。最简单的解决方法是改用 store.reload()。

于 2013-06-13T04:13:33.857 回答
0

也许您在收听 load 事件时来得太早了。我在我的应用程序中做的大致相同(不是滚动到最后,而是加载后的一些任意记录)。我在 store.load() 的回调中执行 view-refresh 和 bufferedrender-scrollTo。

鉴于您的代码,这看起来像:

this.on('afterrender', function (grid) {
      var store = grid.getStore();
      store.load({
          callback: function {
              // snip
              var view = topicPanel.getView();
              view.refresh();
              topicPanel.getPlugin('bufferedrenderer').scrollTo(store.getTotalCount()-1);
           }
      });
});
于 2013-06-13T03:10:12.613 回答