Проблема с динамической настройкой `grid-template-area` - PullRequest
0 голосов
/ 07 октября 2018

Справочная информация : я пишу приложение на vanilla JS, которое может динамически генерировать и обновлять свойства CSS-сетки.В частности, меня интересует настройка grid-template-areas динамически.Этот пример может оказаться запутанным, поэтому вот ссылка CodeSandbox на текущее состояние проекта .


Ожидаемое поведение : я могу установить этисвойства на начальном рендере без проблем.Код для этого выглядит примерно так:

function GridMap(targetElement, { 
    aspectWidth, 
    aspectHeight, 
    density, 
    defaultTrackName = `x` 
}) {

    /* output: [`x x`, `x x`] */
    this.areaMap = Array.from(
        Array(aspectHeight)
            .map(() => `${defaultTrackName} `
                .repeat(aspectWidth)
                .trim()
            )
    )

    /* assign CSS grid properties to target element */
    this.targetElement.style.display = `grid`
    this.targetElement.style.gridTemplateAreas = this.areaMap
        .map(row => `"${row}"`) // output: [`"x x"`, `"x x"`]
        .join(` `) // output: `"x x" " x x"`
}

const target = document.getElementById(`target`)
const grid = new GridMap(target, {
    aspectWidth: 2,
    aspectHeight: 2,
    density: 1,
})

Что приводит к следующему элементу:

<div id="target" style="display: grid; grid-template-areas: "x x" "x x";"></div>

Проблема : приведенный выше код работает при начальном рендере .Это сгенерирует правильный элемент, как я покажу выше.Но когда я пытаюсь сделать это впоследствии с другими (динамически генерируемыми) свойствами, элемент не обновляется.С этого момента трудно выделить код, чтобы привести хороший пример, поэтому - это проект CodeSandbox .Вот как выглядит рассматриваемый код:

function Entity({ trackName, shape }) {
  this.trackName = trackName
  this.shape = shape
    .split(`\n`)
    .filter(track => track)
    .map(track => track.trim())
    .filter(track => track)
}

grid.placeEntity = function placeEntity(
    { x = 0, y = 0 },
    { shape, trackName },
  ) {
    let currentEntityRow = 0

    grid.areaMap = grid.areaMap.map((row, i) => {
      if (currentEntityRow < shape.length) {
        if (i >= y) {
          row = row.split(` `)
          row.splice(
            x,
            shape[currentEntityRow].split(` `).length,
            ...shape[currentEntityRow].split(` `).map(() => trackName),
          )

          row = row.join(` `)
          currentEntityRow += 1
        }
      }

      return row
    })

    grid.update()
}

const entity = new Entity({
    trackName: `entity`,
    shape: `
        o o
        o
    `
})

grid.placeEntity({ x = 1, y = 1 }, entity)

Глядя на вывод консоли в моем примере CodeSandbox , вы видите, что новый grid.areaMap действительно генерируется.Но по какой-то причине при попытке обновить его с помощью grid.placeEntity() обновления не отражаются во вновь отображаемом элементе.


Что я пробовал :

  • Избавляемся от всего вызова grid.placeEntity и:
    • ... прямо устанавливаем element.style.gridTemplateAreas на что-то простое, например "foo bar" "hello world". Это работает, как и ожидалось .
    • ... непосредственно устанавливая element.style.gridTemplateAreas точно такую ​​же строку, которую я генерирую в приведенном выше примере. Это не работает! Это говорит мне, что есть проблема с тем, как я генерирую grid.areaMap, но я не могу указать на эту проблему.

1 Ответ

0 голосов
/ 07 октября 2018

Я обнаружил проблему : Именованные дорожки сетки CSS всегда должны быть смежными и всегда должны образовывать прямоугольник. Пример здесь :

#grid {
  display: grid;
  grid-template-rows: repeat(4, 100px);
  grid-template-columns: repeat(4, 100px);

  /* this isn't valid CSS */
  grid-template-areas:
    'entity-1 entity-2'
    'entity-2 entity-4';

  /* this is valid */
  grid-template-areas:
     'entity-1 entity-2'
     'entity-3 entity-4';
}

Имеет смысл, но отчасти отстой, насколько этот проект пытается сделать.Я уверен, что здесь есть обходной путь!

...