我正准备使用 ExtJS 4 制作一个基本的文件管理器。我现在面临的问题是:如何在单击列时对 grid panel 进行自定义排序。

想象一下,我们有商店领域:

[
    { name: "is_dir", type: "boolean" },
    { name: "name",   type: "string"  },
    { name: "size",   type: "int"     }
]

以及来自数组的数据:
[
    { is_dir: true,  name: "..",        size: 0    },
    { is_dir: false, name: "file2.txt", size: 512  },
    { is_dir: true,  name: "folder2",   size: 0    },
    { is_dir: false, name: "file3.txt", size: 1024 },
    { is_dir: true,  name: "folder1",   size: 0    },
    { is_dir: true,  name: "file1.txt", size: 1024 },
    // ...
]

这个想法是像在任何文件管理器(例如 Total CommanderMCFAR 等)中进行排序,这样:
  • 名称为“..”的项目总是放在顶部
  • 目录在“..”(如果存在)之后按排序顺序
  • 文件按排序顺序放在目录(如果存在)之后

  • 例如,按名称和大小排序的输出应为:
    ^ Name           | Size               Name             | ^ Size
    -----------------------               -------------------------
    ..               | 0                  ..               | 0
    folder1          | 0                  folder1          | 0
    folder2          | 0                  folder2          | 0
    file1.txt        | 1024               file2.txt        | 512
    file2.txt        | 512                file1.txt        | 1024
    file3.txt        | 1024               file3.txt        | 1024
    

    我尝试为商店 sorterFn 属性编写自定义 sorters,但它没有帮助。我相信应该有一些简单的解决方案。

    最佳答案

    您可以覆盖商店的 sort 方法:

    Ext.define('My.store.FileStore', {
        extend: 'Ext.data.Store',
    
        sort: function () {
            this.doSort(function() {
                // Custom sorting function
                console.log(arguments);
                return Math.random() > 0.5 ? 1 : -1; // :)
            });
        }
    });
    

    更新
    Ext.define('FileModel', {
        extend: 'Ext.data.Model',
        fields: [
            { name: "is_dir", type: "boolean" },
            { name: "name",   type: "string"  },
            { name: "size",   type: "int"     }
        ]
    });
    
    Ext.define('FileStore', {
        extend: 'Ext.data.Store',
        model: 'FileModel',
        data: [
            { is_dir: true,  name: "..",        size: 0    },
            { is_dir: false, name: "file2.txt", size: 512  },
            { is_dir: true,  name: "folder2",   size: 0    },
            { is_dir: false, name: "file3.txt", size: 1024 },
            { is_dir: true,  name: "folder1",   size: 0    },
            { is_dir: false, name: "file1.txt", size: 1024 },
        ],
    
        sorters: [{
            property: 'name',
            direction: 'ASC'
        }],
    
        sort: function(params) {
            var dir = params ? params.direction : 'ASC';
            var prop = params ? params.property : 'name';
    
            this.callParent(arguments); // UPDATE 2
    
            this.doSort(function(rec1, rec2) {
                var rec1sort = '';
                var rec2sort = '';
    
                if (rec1.get('is_dir') && rec2.get('is_dir')) {
                    // both dirs
                    if (rec1.get('name') == '..') {
                        return -1;
                    }
                    else if (rec2.get('name') == '..') {
                        return 1;
                    }
                    else {
                        return rec1.get('name').localeCompare(rec2.get('name')) * (dir == 'ASC' ? 1 : -1);;
                    }
                }
                else if (rec1.get('is_dir') != rec2.get('is_dir')) {
                    // file and dir
                    if (rec1.get('is_dir')) {
                        if (rec1.get('name') == '..') {
                            return -2;
                        }
                        else {
                            return -1;
                        }
                    }
                    else {
                        if (rec2.get('name') == '..') {
                            return 2;
                        }
                        else {
                            return 1;
                        }
                    }
                }
                else if (!rec1.get('is_dir') && !rec2.get('is_dir')) {
                    // both files
                    var result;
                    if (typeof rec1.get(prop) == 'number') {
                        result = rec1.get(prop) - rec2.get(prop);
                        if (result == 0) {
                            result = rec1.get('name').localeCompare(rec2.get('name'));
                        }
                    }
                    else {
                        result = rec1.get('name').localeCompare(rec2.get('name'));
                    }
                    return dir == 'ASC' ? result : result * -1;
                }
            });
        }
    });
    
    var grid = Ext.create('Ext.grid.Panel', {
        title: 'Files',
        store: Ext.create('FileStore'),
        renderTo: Ext.getBody(),
        columns: [{
            header: 'Name',
            dataIndex: 'name'
        }, {
            header: 'Size',
            dataIndex: 'size'
        }]
    });
    

    关于javascript - ExtJS 4 Grid 自定义列排序(文件管理器风格),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12932007/

    10-12 07:29
    查看更多