Использование с Svelte

Для использования Gridstack.js в приложениях на Svelte сначала необходимо установить библиотеку через npm:

npm install gridstack

После установки подключение производится через импорт модулей в компоненте Svelte:

<script>
  import { GridStack } from 'gridstack';
  import 'gridstack/dist/gridstack.min.css';
  
  let grid;
</script>

Создаётся контейнер для сетки в разметке Svelte:

<div bind:this={gridElement} class="grid-stack">
  <div class="grid-stack-item" gs-w="4" gs-h="2">
    <div class="grid-stack-item-content">Элемент 1</div>
  </div>
  <div class="grid-stack-item" gs-w="4" gs-h="2">
    <div class="grid-stack-item-content">Элемент 2</div>
  </div>
</div>

Инициализация сетки

Инициализация Gridstack в Svelte производится в блоке onMount для корректного взаимодействия с DOM:

<script>
  import { onMount } from 'svelte';
  import { GridStack } from 'gridstack';
  import 'gridstack/dist/gridstack.min.css';

  let gridElement;
  let gridInstance;

  onMount(() => {
    gridInstance = GridStack.init({
      cellHeight: 80,
      margin: 5,
      draggable: { handle: '.grid-stack-item-content' },
      resizable: { handles: 'all' }
    }, gridElement);
  });
</script>
  • cellHeight — высота ячеек сетки, может быть числом или функцией.
  • margin — отступ между элементами.
  • draggable — настройка перетаскивания элементов.
  • resizable — настройка изменения размеров элементов.

Динамическое добавление и удаление элементов

Для работы с динамическими элементами используется API addWidget и removeWidget:

<script>
  function addWidget() {
    gridInstance.addWidget({
      x: 0, y: 0, w: 3, h: 2,
      content: '<div class="grid-stack-item-content">Новый элемент</div>'
    });
  }

  function removeLastWidget() {
    const items = gridInstance.engine.nodes;
    if(items.length) gridInstance.removeWidget(items[items.length - 1].el);
  }
</script>

<button on:click={addWidget}>Добавить элемент</button>
<button on:click={removeLastWidget}>Удалить последний</button>
  • x, y — координаты элемента на сетке.
  • w, h — ширина и высота в ячейках.
  • content — HTML-контент элемента.

Реактивное связывание с состоянием Svelte

Для синхронизации состояния элементов с внутренним массивом Svelte можно использовать реактивные переменные и подписку на события Gridstack:

<script>
  let widgets = [
    {id: 1, x: 0, y: 0, w: 4, h: 2, content: 'Элемент A'},
    {id: 2, x: 4, y: 0, w: 4, h: 2, content: 'Элемент B'}
  ];

  function renderWidgets() {
    gridInstance.removeAll();
    widgets.forEach(w => {
      gridInstance.addWidget({
        x: w.x, y: w.y, w: w.w, h: w.h,
        content: `<div class="grid-stack-item-content">${w.content}</div>`
      });
    });
  }

  onMount(() => {
    gridInstance = GridStack.init({}, gridElement);
    renderWidgets();

    gridInstance.on('change', function(event, items) {
      items.forEach(item => {
        const index = widgets.findIndex(w => w.id == item.id);
        if(index > -1) {
          widgets[index].x = item.x;
          widgets[index].y = item.y;
          widgets[index].w = item.w;
          widgets[index].h = item.h;
        }
      });
    });
  });
</script>

Использование кастомных компонентов Svelte внутри Gridstack

Gridstack позволяет вставлять полноценные компоненты Svelte в сетку через slot или контейнеры, оборачивая компонент в grid-stack-item:

<div bind:this={gridElement} class="grid-stack">
  {#each components as comp (comp.id)}
    <div class="grid-stack-item" gs-w={comp.w} gs-h={comp.h} gs-x={comp.x} gs-y={comp.y}>
      <svelte:component this={comp.component}/>
    </div>
  {/each}
</div>
  • {#each} используется для динамического рендеринга списка компонентов.
  • svelte:component позволяет рендерить разные компоненты на лету.

Работа с событиями Gridstack

Gridstack предоставляет события для отслеживания действий пользователя:

  • added — элементы добавлены в сетку.
  • removed — элементы удалены.
  • change — изменено положение или размер элемента.
  • dragstart/dragstop — начало и конец перетаскивания.
  • resizestart/resizestop — изменение размеров.

Пример подписки на события:

gridInstance.on('added', function(event, items) {
  console.log('Добавлены элементы:', items);
});

gridInstance.on('change', function(event, items) {
  items.forEach(item => console.log('Изменён элемент:', item));
});

Оптимизация производительности

При работе с большим количеством элементов рекомендуется:

  • Использовать removeAll и последующий addWidget для перерисовки.
  • Ограничивать количество слушателей событий.
  • Применять debounce при обработке событий drag/resize для уменьшения частоты обновлений состояния.

Стилизация и кастомизация

Gridstack использует CSS-классы:

  • grid-stack — контейнер сетки.
  • grid-stack-item — элемент сетки.
  • grid-stack-item-content — содержимое элемента.

Можно применять любые стили через CSS или препроцессоры Svelte:

.grid-stack-item-content {
  background-color: #4CAF50;
  color: white;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 4px;
  font-weight: bold;
}

Также поддерживаются темы и пользовательские классы для отдельных элементов.

Закрепление и ограничения

Gridstack позволяет задавать ограничения для элементов:

  • locked — запрещает перемещение и изменение размера.
  • minW, maxW, minH, maxH — ограничения по размерам.
  • noMove, noResize — отключение взаимодействия.
gridInstance.addWidget({
  x: 0, y: 0, w: 4, h: 2,
  content: '<div class="grid-stack-item-content">Фиксированный элемент</div>',
  locked: true
});

Эти возможности позволяют создавать интерактивные панели управления, дашборды и динамические интерфейсы с гибким управлением расположением элементов.