【问题标题】:Issue with dynamically setting `grid-template-areas`动态设置“grid-template-areas”的问题
【发布时间】:2018-10-07 07:09:52
【问题描述】:

背景:我正在用 vanilla JS 编写一个可以动态生成和更新 CSS 网格属性的应用程序。特别是,我对动态设置grid-template-areas 很感兴趣。这个例子可能很复杂,所以here's a CodeSandbox link to the current state of the project


预期行为:我可以在初始渲染时设置这些属性,没有任何问题。代码如下所示:

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>

问题:上面的代码在初始渲染时工作。它将生成一个正确的元素,如我上面所示。但是当我之后尝试使用不同的(动态生成的)属性时,元素不会得到更新。从这一点开始,很难隔离代码来给出一个很好的例子,所以here's the project so far on 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 example 中的控制台输出,您会看到确实生成了新的grid.areaMap。但由于某种原因,当尝试通过grid.placeEntity() 对其进行更新时,更新不会反映在新渲染的元素中。


我的尝试

  • 摆脱整个grid.placeEntity 呼叫并且:
    • ...直接将element.style.gridTemplateAreas 设置为"foo bar" "hello world" 之类的简单对象。 这按预期工作
    • ...直接将element.style.gridTemplateAreas 设置为我在上面的示例中生成的完全相同的字符串。 这不起作用!这告诉我生成grid.areaMap 的方式存在问题,但我无法指出该问题。

【问题讨论】:

    标签: javascript css css-grid


    【解决方案1】:

    我发现了问题:命名的 CSS 网格轨道必须始终相邻并且必须始终形成一个矩形。 Example here:

    #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';
    }
    

    有道理,但就这个项目试图做的事情而言,有点糟糕。我敢肯定在这里可以找到解决方法!

    【讨论】:

      猜你喜欢
      • 2018-01-19
      • 2017-08-18
      • 2019-02-13
      • 2023-03-16
      • 2020-08-27
      • 2021-06-19
      • 1970-01-01
      • 1970-01-01
      • 2017-09-13
      相关资源
      最近更新 更多