0

使用 RactiveJS、Redux 和 Gridstack 制作的应用程序。

添加新小部件时,一切都很好,小部件也可以移动/调整大小。但是当我删除所有小部件并添加例如两个新小部件时,然后:

  1. 小部件不能移动,也不能调整大小。如图:
  2. 当尝试删除小部件时,它会消失,但其他小部件会改变它们的位置。

您可以看到右侧的小部件移动到右侧,但句柄保持在原位

jsFiddle提供如下

您可以看到右侧的小部件移动到右侧,但句柄保持在原位。那么为什么会出现这种行为以及如何处理呢?

RactiveJS 应用程序具有三个组件

DashboardComponent
WidgetGridComponent
WidgetComponent

提供的代码如下:

var Widget = Ractive.extend({
    isolated: false, // To pass events to WidgetGrid component (makeWidget, removeWidget, etc.)
    template: '#widgetTemplate',
    components: {},
    oninit: function() {
        // Load data to widget
    },
    oncomplete: function() {
        this.drawChart();
    },

    drawChart: function() {
        var self = this;

        function exampleData() {
            return [{
                    "label": "One",
                    "value": 29.765957771107
                },
                {
                    "label": "Two",
                    "value": 0
                },
                {
                    "label": "Three",
                    "value": 32.807804682612
                },
                {
                    "label": "Four",
                    "value": 196.45946739256
                },
                {
                    "label": "Five",
                    "value": 0.19434030906893
                },
                {
                    "label": "Six",
                    "value": 98.079782601442
                },
                {
                    "label": "Seven",
                    "value": 13.925743130903
                },
                {
                    "label": "Eight",
                    "value": 5.1387322875705
                }
            ];
        }
        nv.addGraph(function() {
            var chart = nv.models.pieChart()
                .x(function(d) {
                    return d.label
                })
                .y(function(d) {
                    return d.value
                })
                .showLabels(true);

            d3.select("#widget" + self.get("id") + " svg")
                .datum(exampleData())
                .transition().duration(350)
                .call(chart);

            return chart;
        });

    },

    data: function() {
        return {
            id: null,
            x: null,
            y: null,
            width: null,
            height: null,
        }
    }
});

var WidgetGrid = Ractive.extend({
    // isolated:false,
    // twoway:false,

    template: '#widgetGridTemplate',
    components: {
        Widget: Widget,
    },
    onrender: function() {
        // Init gridstack instance
        this.bindGridstack();
    },

    deleteWidget: function(id) {
        Action.deleteWidget(id);
    },

    removeWidget: function(id) {
        $(".grid-stack").data("gridstack").removeWidget("#widget" + id);
    },

    createWidget: function(id) {
        $(".grid-stack").data("gridstack").makeWidget("#widget" + id);
    },

    updateWidgetSize: function(id, width, height) {
        Action.updateWidgetSize(id, width, height);
    },
    updateWidgetPosition: function(id, x, y) {
        Action.updateWidgetPosition(id, x, y);
    },

    bindGridstack: function() {
        var self = this;
        var options = {
            animate: true,
            auto: false, // if false gridstack will not initialize existing items (default: true)
            float: true, // enable floating widgets (default: false)
            disableOneColumnMode: true,
            width: 10, //  amount of columns (default: 12)
            height: 10, // maximum rows amount. Default is 0 which means no maximum rows
            // height: 10,
            // cellHeight: 80,
            disableResize: false,
            disableDrag: false,
            verticalMargin: 0,
            resizable: {
                handles: 'se'
            }
        };
        var grid = $(".grid-stack").gridstack(options);

        // On user ends resizing
        grid.on('gsresizestop', function(event, elem) {
            var $el = $(elem);
            var node = $el.data('_gridstack_node');
            var id = node.el.attr("id").replace("widget", "");

            self.updateWidgetSize(id, node.width, node.height, node.el.css("width"), node.el.css("height"));
        });

        // On user ends dragging
        grid.on('dragstop', function(event, ui) {
            var $el = $(event.target);
            var node = $el.data('_gridstack_node');
            var id = $el.attr("id").replace("ar-widget", "");

            self.updateWidgetPosition(id, node.x, node.y);
        });
    },

    data: function() {
        return {
            widgets: [],
        }
    }
});

var Dashboard = Ractive.extend({
    el: '#dashboard', //document.body,
    template: '#dashboardTemplate',
    isolated: true,
    append: false,
    oninit: function() {
        this.on("add", function() {
            Action.addWidget()
        });
    },
    components: {
        WidgetGrid: WidgetGrid,
    },
    data: function() {
        return {
            store: {}
        }
    }
});
4

1 回答 1

1

里面有几个问题:

  • detach取消渲染组件时不调用。只有在被调用时ractive.detach()才会调用它。您的网格不知道小部件的删除。在 Ractive 取消渲染小部件元素后,这会导致网格表现得很奇怪。

  • 另一方面,grid.removeWidget()从 DOM 中删除小部件。状态改变后,Ractive 仍然会尝试取消渲染。但是由于该元素不再存在并且因为 Ractive 不知道该小部件的删除,它会导致双重删除。

  • 状态更改后,小部件的数据不再存在。id已经是undefinedid处理teardown,unrender事件时不能再使用destruct。您必须提前断开小部件与网格的连接,最好是在状态更改之前。

理想情况下,您应该只让 Ractive 进行元素的渲染/取消渲染,并且只通知 gridstack 有关从网格创建/断开小部件的信息。您已经通过使用makeWidget而不是在渲染上执行此操作addWidget。对于删除,您只需要做同样的事情。removeWidget接受第二个参数,如果false,它将取消小部件与网格的关联,但不会从 DOM 中删除元素。这使得在状态更改后未渲染到 Ractive。

这是一个例子:https ://jsfiddle.net/fm133mk6/

于 2017-08-31T00:51:32.597 回答