【问题标题】:Store/extract array of integers within element attributes [closed]在元素属性中存储/提取整数数组[关闭]
【发布时间】:2020-02-22 21:06:30
【问题描述】:

我正在尝试基于 JavaScript 中的 2d 网格构建游戏。

在嵌套的 for 循环中,我这样设置单元格的数据属性:

cell.setAttribute('data-pos',[i,j]);

在我的事件处理程序中,我得到如下数据:

let pos = event.target.getAttribute('data-pos');

当我尝试访问 pos 的元素时,发生了一些奇怪的事情。

对于具有data-pos[1, 3] 的单元格,

当我使用console.log:时得到以下值

pos[0] = 1
pos[1] = ,
pos[2] = 3

不知何故,逗号被视为数组元素。

这是为什么以及如何正确地将 ij 的值传递给事件处理程序?

【问题讨论】:

  • 您已经对数组进行了字符串化。我真的不建议像这样在 DOM 中存储状态,因为您将对其进行序列化和反序列化。建议使用数据结构重新设计。你能显示minimal reproducible example吗?谢谢!
  • 我是怎么做到的? let pos = event.target.getAttribute('data-pos'); 在没有引号的情况下给出错误。
  • DOM中的属性总是字符串——如果你把[i,j]这样的数组放入setter,JS会为你调用[i,j].toString()

标签: javascript arrays dom-events


【解决方案1】:

正如@ggorlen 在 cmets 中指出的那样,cell.setAttribute('data-pos',[i,j]) 行将'1,3'字符串 值分配给您的data-pos 属性(因为它的值不能是数组)。

如果这对您来说没问题,您可以通过以下方式将数据重新放入数组中:

let pos = event.target.getAttribute('data-pos').split(',')

如果您希望将数据传递给 DOM 并在单击时将其取回并避免解析字符串化值,您可以引入 2 个data-* 属性,例如data-pos-i/data-pos-j

const cells = ((i,j) => Array.from(
                {length:i*j},
                (_,k) => ({id:k, i:k%j, j:0|(k/j)%i}))
              )(5,3),
      matrix = (flatArr => 
                  flatArr.reduce((r,{id,i,j},k) => 
                    (r[i]=(r[i]||[]), r[i][j] = {id, i, j}, r), [])
               )(cells),
      tableHTML = (tableData => {
                    const rowsHTML = tableData
                                      .map(tableRow => 
                                          '<tr>'+tableRow.map(({id,i,j}) => `<td id=${id} data-pos-i="${i}" data-pos-j="${j}"></td>`).join('')+'</tr>')
                                      .join('')
                    return `<table>${rowsHTML}</table>`
                  })(matrix),
      mytable = document.getElementById('mytable')
      
mytable.innerHTML = tableHTML

mytable.addEventListener('click', ({target}) => {
  const cellData = {i:target.dataset.posI, j:target.dataset.posJ}
  console.log(cellData)
})
#mytable td {
  display: table-cell;
  width: 20px;
  height: 20px;
  background: grey;
  cursor: pointer;
}

#mytable td:hover {
  background: #fff;
}
&lt;table id="mytable"&gt;&lt;/table&gt;

但是,更好的方法是不要在状态和 DOM 之间来回反弹您的数据。

相反,您可以将单元格存储为一个平面对象数组,其中每个单元格对象都有ij-坐标绑定到唯一的id(以及其他必要的数据),因此点击后您可以通过 id 查找任何绑定数据:

const cells = ((i,j) => Array.from(
                {length:i*j},
                (_,k) => ({id:k, i:k%j, j:0|(k/j)%i}))
              )(5,3),
      matrix = (flatArr => 
                  flatArr.reduce((r,{id,i,j},k) => 
                    (r[i]=(r[i]||[]), r[i][j] = id, r), [])
               )(cells),
      tableHTML = (tableData => {
                    const rowsHTML = tableData
                                      .map(tableRow => 
                                          '<tr>'+tableRow.map(cellData => `<td id=${cellData}></td>`).join('')+'</tr>')
                                      .join('')
                    return `<table>${rowsHTML}</table>`
                  })(matrix),
      mytable = document.getElementById('mytable')
      
mytable.innerHTML = tableHTML

mytable.addEventListener('click', ({target}) => {
  const cellData = cells.find(({id}) => id == target.id)
  console.log(cellData)
})
#mytable td {
  display: table-cell;
  width: 20px;
  height: 20px;
  background: grey;
  cursor: pointer;
}

#mytable td:hover {
  background: #fff;
}
&lt;table id="mytable"&gt;&lt;/table&gt;

【讨论】:

  • 很好,但即使这样也不能完全恢复数据。您需要使用event.target.getAttribute('data-pos').split(',').map(Number) 解析整数。哎哟。所有这些额外的工作都应该表明这是一个糟糕的设计。希望 OP 可以解释他们真正想要做什么,并避免x-y problem 这可能是。
  • 所以帮助我使用更好的设计 - 我怎样才能正确地将二维数组索引传递给事件处理程序,或者甚至试图做那部分糟糕的设计?
  • @ggorlen :是的,初始设计需要改进,因此元素属性不能存储数组这一事实应该鼓励 OP 引入 2 个属性,例如 data-pos-i/data-pos-j 将 2 个值分别存储在属性
  • @RobinAndrews :查看我的评论以获取有关更好方法的提示
  • 不,我也不会那样做。如果 OP 正在制作游戏,请将所有状态保留在脚本中,而不是 DOM。编写一个const cells = [] 数组并将对象放入其中(或类似的东西,因为没有minimal reproducible example,所以无法判断)。然后,当需要渲染单元格时,根据 JS 脚本中的数据渲染它们。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-25
  • 2021-03-11
  • 2015-06-26
  • 2013-04-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多