JavaScript 在我添加一个中断后销毁所有 children?
JavaScript destroys all children after I append a break?
我正在创建一个脚本,该脚本接受两个输入维度、宽度和高度,并创建一个缩放网格,该网格表示具有给定尺寸的框中可以容纳多少块,函数如下:
function makeRow() {
for (var i = 1; i <= blocksTall; i++) {
var mb = document.createElement("div");
mb.setAttribute("class", "matrix-block mb-off");
mb.setAttribute("onClick", "select_mb('" + j + "," + i + "');");
placeBlocks.appendChild(mb);
if (i = blocksWide) {
placeBlocks.appendChild('br');
}
}
}
这个函数可以很好地显示块的第一行,然后在该行完成渲染后插入一个 break 标记,这正是我想要做的。问题是我需要再生成 17 行,具有相同数量的块,每个块都在前一行下面,所以我的第一个想法是,我将在第一个 for 循环周围再包装一个 for 循环,因为有一个 break在那里,它将在前一行下方呈现新行:
for (var j = 1; j <= blocksTall; j++) { // Vertical for loop.
for (var i = 1; i <= blocksWide; i++) { // Horizontal for loop.
var mb = document.createElement("div");
//mb.setAttribute("id", "matblock-" + i + "-" + j);
mb.setAttribute("class", "matrix-block mb-off");
mb.setAttribute("onClick", "select_mb('" + i + "," + j + "');");
placeBlocks.appendChild(mb);
}
if (j = blocksWide) {
placeBlocks.appendChild(brk);
}
}
其中 blocksWide
= 17。Here is a fiddle 包含完整的脚本。当我在控制台中记录 j 的值时,它实际上会递增(这告诉我 for 循环正在运行)。似乎正在发生的事情是由于某种原因渲染该行,然后在其顶部渲染新行(似乎不太可能,因为 break 标记在每行完成后渲染)或者由于某种原因 [=每次新的 "horizontal" for 循环是 运行.
时,27=] 都会被销毁
有谁知道为什么会发生这种情况,以及如何正确地将每一行附加到最后一行下面,以便生成块网格而不是仅仅一行?
在此先致谢,非常感谢任何帮助。
所以,我对你脚本的某些方面有点困惑,但我认为你有两个主要问题。
首先,您只调用 document.createElement("br")
一次,这意味着您只创建一个换行符;并且单个换行符只能出现在 DOM 中的一处。这个:
placeBlocks.appendChild(brk);
从 DOM 中的当前位置删除 brk
,然后将其放在 placeBlocks
的末尾。您应该将其更改为:
placeBlocks.appendChild(document.createElement("br"));
其次,我认为if (j = blocksWide) {
没有道理。请注意,它等同于:
j = blocksWide;
if (blocksWide != 0) {
这意味着它通过操纵 j
的值来干扰您的 for 循环。我认为该问题的解决方法是简单地删除整个 if
-check,并无条件地执行其主体。
我真的不明白你想用余数运算符和除法做什么,但是 blocksWide
解析为无穷大导致无限循环,而 blocksHigh
只是 17。所有full
之外的其他变量未被使用。
您实际上不需要两个循环,尽管这样做是可以的。如果你只想使用一个循环,你基本上只需要知道 i
是否是 dispW
的倍数。
所以你用 i
除以 dispW
然后你想知道它是否是一个整数,要找到这个你使用 1
的余数运算符,如果它解析为 0
是整数。看起来像这样...
if ((i / dispW) % 1 === 0)
// if ( dispW=3 && ( i=3 || i=6 || i=9 || ... ) ) true;
这个循环看起来像
totalWidth = dispW * dispH; // total number of blocks
for (var i = 1; i <= totalWidth; i++) {
// do stuff;
if((i / dispW) % 1 === 0) {
// insert new line break;
}
}
您用于 select 积木的方法是一种迂回的方法。首先你不应该使用内联 javascript,其次你不应该使用 javascript 将内联 javascript 嵌入动态创建的元素中。请改用 element.onclick = function;
。
注意函数后面没有大括号。这是因为您实际上传递的是函数引用而不是函数的返回值。
element.onclick
将事件对象传递给函数引用。您可以使用它来 select 像这样被点击的块。
for ( ... ) {
...
var element = document.createElement('div');
element.onclick = myFunction;
...
}
function myFunction(e) {
var clicked = e.target // this is the element that was clicked on
}
另外,您在循环之外创建了一个 <br>
元素。因为 appendChild
移动元素而不创建元素,所以它只会继续移动换行符直到循环结束。它应该是这样的。
placeBox.appendChild(document.createElement('br'))
// append a newly created line break;
那么即使所有逻辑都按预期工作并且您每次都创建一个新的换行符,浮动块意味着没有换行符,而是使用 display: inline-block;
。
所以最后你得到的是...
window.onload = function () {
renderGrid();
};
function renderGrid() {
var blocksTall = document.getElementById('height-in').value;
var blocksWide = document.getElementById('width-in').value;
var blocksTotal = blocksWide * blocksTall;
var placeBlocks = document.getElementById('matrix-shell');
while (placeBlocks.firstChild) {
placeBlocks.firstChild.remove();
}
console.log(blocksWide + "/" + blocksTall);
for (var i = 1; i <= blocksTotal; i++) {
var mb = document.createElement("div");
mb.className = 'matrix-block mb-off';
mb.onclick = select_mb;
placeBlocks.appendChild(mb);
if (((i / blocksWide) % 1) === 0) {
var brk = document.createElement("br");
placeBlocks.appendChild(brk);
}
}
}
function select_mb(e) {
var cur_mb = e.target;
if (cur_mb.className == "matrix-block mb-off") {
// Turn cell on.
cur_mb.style.backgroundColor = "#00FF00";
cur_mb.className = "matrix-block mb-on";
} else {
//Turn cell off.
cur_mb.style.backgroundColor = "#000";
cur_mb.className = "matrix-block mb-off";
}
}
.matrix-block {
height: 10px;
width: 10px;
border: 1px solid #fff;
display: inline-block;
background-color: black;
}
.mb-off {
background-color: black;
}
#matrix-shell {
font-size: 0;
display: inline-block;
border: 1px solid red;
white-space: nowrap;}
<table>
<tr>
<td>Width:</td>
<td>
<input id="width-in" name="width-in" type="text" />
</td>
</tr>
<tr>
<td>Height:</td>
<td>
<input id="height-in" name="height-in" type="text" />
</td>
</tr>
<tr>
<td colspan="2">
<button onClick="renderGrid()">Compute</button>
</td>
</tr>
</table>
<br/>
<div id="matrix-shell"></div>
我正在创建一个脚本,该脚本接受两个输入维度、宽度和高度,并创建一个缩放网格,该网格表示具有给定尺寸的框中可以容纳多少块,函数如下:
function makeRow() {
for (var i = 1; i <= blocksTall; i++) {
var mb = document.createElement("div");
mb.setAttribute("class", "matrix-block mb-off");
mb.setAttribute("onClick", "select_mb('" + j + "," + i + "');");
placeBlocks.appendChild(mb);
if (i = blocksWide) {
placeBlocks.appendChild('br');
}
}
}
这个函数可以很好地显示块的第一行,然后在该行完成渲染后插入一个 break 标记,这正是我想要做的。问题是我需要再生成 17 行,具有相同数量的块,每个块都在前一行下面,所以我的第一个想法是,我将在第一个 for 循环周围再包装一个 for 循环,因为有一个 break在那里,它将在前一行下方呈现新行:
for (var j = 1; j <= blocksTall; j++) { // Vertical for loop.
for (var i = 1; i <= blocksWide; i++) { // Horizontal for loop.
var mb = document.createElement("div");
//mb.setAttribute("id", "matblock-" + i + "-" + j);
mb.setAttribute("class", "matrix-block mb-off");
mb.setAttribute("onClick", "select_mb('" + i + "," + j + "');");
placeBlocks.appendChild(mb);
}
if (j = blocksWide) {
placeBlocks.appendChild(brk);
}
}
其中 blocksWide
= 17。Here is a fiddle 包含完整的脚本。当我在控制台中记录 j 的值时,它实际上会递增(这告诉我 for 循环正在运行)。似乎正在发生的事情是由于某种原因渲染该行,然后在其顶部渲染新行(似乎不太可能,因为 break 标记在每行完成后渲染)或者由于某种原因 [=每次新的 "horizontal" for 循环是 运行.
有谁知道为什么会发生这种情况,以及如何正确地将每一行附加到最后一行下面,以便生成块网格而不是仅仅一行?
在此先致谢,非常感谢任何帮助。
所以,我对你脚本的某些方面有点困惑,但我认为你有两个主要问题。
首先,您只调用 document.createElement("br")
一次,这意味着您只创建一个换行符;并且单个换行符只能出现在 DOM 中的一处。这个:
placeBlocks.appendChild(brk);
从 DOM 中的当前位置删除 brk
,然后将其放在 placeBlocks
的末尾。您应该将其更改为:
placeBlocks.appendChild(document.createElement("br"));
其次,我认为if (j = blocksWide) {
没有道理。请注意,它等同于:
j = blocksWide;
if (blocksWide != 0) {
这意味着它通过操纵 j
的值来干扰您的 for 循环。我认为该问题的解决方法是简单地删除整个 if
-check,并无条件地执行其主体。
我真的不明白你想用余数运算符和除法做什么,但是 blocksWide
解析为无穷大导致无限循环,而 blocksHigh
只是 17。所有full
之外的其他变量未被使用。
您实际上不需要两个循环,尽管这样做是可以的。如果你只想使用一个循环,你基本上只需要知道 i
是否是 dispW
的倍数。
所以你用 i
除以 dispW
然后你想知道它是否是一个整数,要找到这个你使用 1
的余数运算符,如果它解析为 0
是整数。看起来像这样...
if ((i / dispW) % 1 === 0)
// if ( dispW=3 && ( i=3 || i=6 || i=9 || ... ) ) true;
这个循环看起来像
totalWidth = dispW * dispH; // total number of blocks
for (var i = 1; i <= totalWidth; i++) {
// do stuff;
if((i / dispW) % 1 === 0) {
// insert new line break;
}
}
您用于 select 积木的方法是一种迂回的方法。首先你不应该使用内联 javascript,其次你不应该使用 javascript 将内联 javascript 嵌入动态创建的元素中。请改用 element.onclick = function;
。
注意函数后面没有大括号。这是因为您实际上传递的是函数引用而不是函数的返回值。
element.onclick
将事件对象传递给函数引用。您可以使用它来 select 像这样被点击的块。
for ( ... ) {
...
var element = document.createElement('div');
element.onclick = myFunction;
...
}
function myFunction(e) {
var clicked = e.target // this is the element that was clicked on
}
另外,您在循环之外创建了一个 <br>
元素。因为 appendChild
移动元素而不创建元素,所以它只会继续移动换行符直到循环结束。它应该是这样的。
placeBox.appendChild(document.createElement('br'))
// append a newly created line break;
那么即使所有逻辑都按预期工作并且您每次都创建一个新的换行符,浮动块意味着没有换行符,而是使用 display: inline-block;
。
所以最后你得到的是...
window.onload = function () {
renderGrid();
};
function renderGrid() {
var blocksTall = document.getElementById('height-in').value;
var blocksWide = document.getElementById('width-in').value;
var blocksTotal = blocksWide * blocksTall;
var placeBlocks = document.getElementById('matrix-shell');
while (placeBlocks.firstChild) {
placeBlocks.firstChild.remove();
}
console.log(blocksWide + "/" + blocksTall);
for (var i = 1; i <= blocksTotal; i++) {
var mb = document.createElement("div");
mb.className = 'matrix-block mb-off';
mb.onclick = select_mb;
placeBlocks.appendChild(mb);
if (((i / blocksWide) % 1) === 0) {
var brk = document.createElement("br");
placeBlocks.appendChild(brk);
}
}
}
function select_mb(e) {
var cur_mb = e.target;
if (cur_mb.className == "matrix-block mb-off") {
// Turn cell on.
cur_mb.style.backgroundColor = "#00FF00";
cur_mb.className = "matrix-block mb-on";
} else {
//Turn cell off.
cur_mb.style.backgroundColor = "#000";
cur_mb.className = "matrix-block mb-off";
}
}
.matrix-block {
height: 10px;
width: 10px;
border: 1px solid #fff;
display: inline-block;
background-color: black;
}
.mb-off {
background-color: black;
}
#matrix-shell {
font-size: 0;
display: inline-block;
border: 1px solid red;
white-space: nowrap;}
<table>
<tr>
<td>Width:</td>
<td>
<input id="width-in" name="width-in" type="text" />
</td>
</tr>
<tr>
<td>Height:</td>
<td>
<input id="height-in" name="height-in" type="text" />
</td>
</tr>
<tr>
<td colspan="2">
<button onClick="renderGrid()">Compute</button>
</td>
</tr>
</table>
<br/>
<div id="matrix-shell"></div>