【问题标题】:Prevent duplicates created by Mithril while sorting elements with SortableJS使用 SortableJS 对元素进行排序时防止 Mithril 创建的重复项
【发布时间】:2020-09-15 12:01:49
【问题描述】:

我正在制作仪表板创建工具。仪表板是一组行,每一行都有框。所以我试图列出项目列表。项目可以在列表之间移动。列表可以在彼此之间进行排序。 一切都保存在一个对象中,可以很容易地以 JSON 格式导出。很酷。

_________          ______________
| A  B  |   move   | A  B  C  C |  
|-------|   C up   |------------|   
| C     |   ===>   |            |  
|_______|          |____________|

如果我将框 C 移动到第一行并调用重绘,则 C 框会复制自身。一个 C 是第二行的原始盒子,第二个 C 盒子是由模型中的秘银创建的。

关键是我只想在行之间移动框,而不是复制它。

我尝试使用 onbeforeupdate 和 m.redraw(),但这不是解决方案,因为我需要进行重绘循环。

class Grid {

    private boxMap = new Map<TDashboardBox, IEditor>();

    constructor(
        public readonly dashboard: DashboardDAO,
        private readonly editorFactory: IBoxFactory
    ) {
        for (const row of dashboard.dashboard.config) {
            for (const box of row) {
                this.boxMap.set(box, editorFactory.create(box.title, box))
            }
        }
    }

    public boxView(box: TDashboardBox): Vnode {
        return m(this.boxMap.get(box) || null);
    }

    public rowView(row: TDashboardRow): Vnode[] {
        return row.map(b => m('.Box', {}, this.boxView(b)));
    }

    public view(): Vnode {
        return m('.Grid', {},
            this.dashboard.dashboard.config.map(r => m('.Row',  {}, this.rowView(r)))
        );
    }

    public oncreate(vnode: VnodeDOM): void {
        Sortable.create(<HTMLElement>vnode.dom, {
            group: "rows",
            animation: 150,
            onEnd: (e: SortableEvent) => {
                this.dashboard.swapRows(e.oldIndex, e.newIndex);
            },
        });

        const rows = vnode.dom.getElementsByClassName('Row');
        for (let i = 0; i < rows.length; i++)
        {
            const row = <HTMLElement>rows[i];
            Sortable.create(row, {
                group: "boxes",
                animation: 150,
                onEnd: (e: SortableEvent) => {
                    const children = e.from.parentElement.childNodes;
                    // Search row indexes of "from row" and "to row"
                    let fromIndex, targetIndex;
                    for (let j = 0; j < children.length; j++) {
                        if (children[j] === e.from) {
                            fromIndex = j;
                        }
                        if (children[j] === e.to) {
                            targetIndex = j;
                        }
                        if (fromIndex !== undefined && targetIndex !== undefined) {
                            break;
                        }
                    }
                    this.dashboard.moveBox(fromIndex, e.oldDraggableIndex, targetIndex, e.newDraggableIndex);

                    m.redraw();
                },
            });
        }
    }
}

编辑 1

可以在 onEnd() 回调中删除复制的框。它解决了复制问题。

如果我在一行上交换盒子,它们会在模型中交换。但重绘后在屏幕上它们被交换回来。

编辑 2

我找到了一些解决方案。差不多了。

// End of onEnd() event
// if boxes moved, then...
m.render(vnode.dom, m(this)); // redraw Grid scratch

我只是扔掉了整个 Grid 的 html,让秘银重建它。

但现在在 Grid 中只是没有事件的 HTML,没有重绘周期。

【问题讨论】:

    标签: typescript mithril.js sortablejs


    【解决方案1】:

    好的,我想通了。 它不是“同类最佳”的解决方案,但效果很好。

    我创建了从其父组件传递给 Grid 组件的回调函数。移动框后,该回调函数会简单地销毁 Grid 并创建新的。

    父组件

    public recreateGrid(): void {
        this.grid = new Grid(
            this.editor.currentDashboard,
            this.factory,
            () => this.recreateGrid()
        )
    }
    ...
    
    public view(): Vnode { // example of view method 
         return m('.Layout.selected-dashboard', {}, [
             ... // some other components
             m(this.grid),
         ]);
    }
    
    

    网格构造函数

    constructor(
        public readonly dashboard: DashboardDAO,      // model
        private readonly editorFactory: IBoxFactory,  // boxes factory
        private readonly onBoxMoved: ()=>void,        // callback       <--
        ) { ... }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-05-20
      • 1970-01-01
      • 1970-01-01
      • 2013-09-11
      • 1970-01-01
      • 2020-11-23
      • 2023-03-25
      • 1970-01-01
      相关资源
      最近更新 更多