You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ExtJS 6.0.1 TreeView如何重复显示指定记录(作为收藏栏)

实现ExtJS TreeStore收藏节点同步到独立树面板的方案

嘿,这个需求我之前在ExtJS 6.0.1里落地过,核心思路是通过节点引用关联两个TreeStore,完全避免数据重复,同时监听favourite属性的变化来自动同步收藏树的内容。下面给你一步步拆解实现方式:

1. 核心设计思路

我们不需要复制节点数据,而是直接将主树中标记为收藏的节点引用到收藏树的根节点下。因为ExtJS的Model实例是引用类型,修改主树节点的favourite属性,收藏树里的对应节点会自动同步,反过来操作收藏树的节点也会同步回主树,完美解决数据重复问题。

2. 具体实现步骤

第一步:定义统一的Model

先确保主树和收藏树使用同一个Model,保证数据结构一致:

Ext.define('MyApp.model.TreeNode', {
    extend: 'Ext.data.Model',
    fields: [
        'text',
        {name: 'favourite', type: 'boolean', defaultValue: false}
    ]
});

第二步:配置主TreeStore并添加监听

在主Store中监听节点的update事件,当favourite属性变化时,自动同步到收藏树:

const mainTreeStore = Ext.create('Ext.data.TreeStore', {
    model: 'MyApp.model.TreeNode',
    root: {
        text: '全部内容',
        expanded: true,
        children: [
            {text: '项目文档', favourite: false},
            {text: '常用工具', favourite: true},
            // 更多初始节点...
        ]
    },
    listeners: {
        update: function(store, record) {
            // 仅当favourite属性发生变化时触发同步
            if (record.get('favourite') !== record.previousValues.favourite) {
                this.syncFavouriteNode(record);
            }
        },
        // 自定义同步方法
        syncFavouriteNode: function(record) {
            const favTree = Ext.getCmp('favouritesTreePanel');
            const favRoot = favTree.getStore().getRootNode();

            if (record.get('favourite')) {
                // 避免重复添加:检查节点是否已在收藏树中
                if (!favRoot.contains(record)) {
                    favRoot.appendChild(record);
                }
            } else {
                // 取消收藏时从收藏树移除节点
                if (favRoot.contains(record)) {
                    record.remove();
                }
            }
        }
    }
});

第三步:配置收藏TreeStore和TreePanel

初始化收藏树时,自动把主树中已标记为收藏的节点加进去,同时绑定到独立的TreePanel:

// 初始化收藏Store,自动加载主树中已收藏的节点
const favouritesStore = Ext.create('Ext.data.TreeStore', {
    model: 'MyApp.model.TreeNode',
    root: {
        text: '我的收藏',
        expanded: true,
        children: mainTreeStore.getRootNode().queryBy(node => node.get('favourite')).getRange()
    }
});

// 创建收藏树面板
Ext.create('Ext.tree.Panel', {
    id: 'favouritesTreePanel',
    title: '我的收藏',
    store: favouritesStore,
    width: 300,
    columns: [
        {xtype: 'treecolumn', dataIndex: 'text', flex: 1},
        // 可选:保留收藏切换图标,操作会同步回主树
        {
            xtype: 'actioncolumn',
            items: [{
                icon: 'resources/icons/unfav.png',
                getClass: function(v, meta, rec) {
                    return rec.get('favourite') ? 'fav-icon' : 'unfav-icon';
                },
                handler: function(grid, rowIndex) {
                    const record = grid.getStore().getAt(rowIndex);
                    record.set('favourite', !record.get('favourite'));
                }
            }]
        }
    ]
});

第四步:额外优化点

  • 远程数据加载同步:如果主树是从远程加载数据,要在主Store的load事件里重新同步收藏树,确保新加载的已收藏节点被加入收藏树。
  • 收藏树排序:可以给收藏Store添加排序规则,比如按节点名称或者收藏时间排序:
    favouritesStore.sort('text', 'ASC');
    
  • 保护根节点:设置收藏树的根节点为不可选择、不可编辑,避免误操作删除根节点:
    root: {
        text: '我的收藏',
        expanded: true,
        selectable: false,
        editable: false
    }
    

效果验证

  • 当你在主树中点击actioncolumn图标标记为收藏时,该节点会自动出现在收藏树的"我的收藏"节点下;
  • 取消收藏时,节点会从收藏树中移除;
  • 无论操作主树还是收藏树的节点,两边的favourite状态都会实时同步,且完全没有数据重复。

内容的提问来源于stack exchange,提问作者trouserboycott

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 06:30:57