重构臃肿代码的好方法是什么?
What's a good way to refactor my bloated code?
我制作了一个简单的 D&D 骰子滚动应用程序进行练习,发现其中有很多重复代码。不过,我找不到自己重构它的好方法。任何提示表示赞赏。公平警告,我是一个菜鸟,所以我已经知道它可能有比我知道的更多的问题。放心真的让我拥有。
https://jsfiddle.net/sakonexus/nd82qjec/
function calcRoll(e) {
let die = e.target.previousElementSibling.name;
let rolls = e.target.previousElementSibling.value;
let topRow = {};
let bottomRow = {};
let randomRoll = 0;
if (rolls == '') {
rolls = 0;
}
if (die.includes("d4")) {
topRow = document.getElementById("d4-roll-results").insertRow(0);
bottomRow = document.getElementById("d4-roll-results").insertRow(1);
topRow.insertCell(0).innerHTML = "Roll Count";
bottomRow.insertCell(0).innerHTML = "Roll Result";
for(i = 0; i < rolls; i++) {
topRow.insertCell(i + 1).innerHTML = i + 1;
}
for(j = 0; j < rolls; j++) {
randomRoll = Math.floor(Math.random() * 4) + 1;
bottomRow.insertCell(j + 1).innerHTML = randomRoll;
}
} else if (die.includes("d6")) {
topRow = document.getElementById("d6-roll-results").insertRow(0);
bottomRow = document.getElementById("d6-roll-results").insertRow(1);
topRow.insertCell(0).innerHTML = "Roll Count";
bottomRow.insertCell(0).innerHTML = "Roll Result";
for(i = 0; i < rolls; i++) {
topRow.insertCell(i + 1).innerHTML = i + 1;
}
for(j = 0; j < rolls; j++) {
randomRoll = Math.floor(Math.random() * 6) + 1;
bottomRow.insertCell(j + 1).innerHTML = randomRoll;
}
} else if (die.includes("d8")) {
topRow = document.getElementById("d8-roll-results").insertRow(0);
bottomRow = document.getElementById("d8-roll-results").insertRow(1);
topRow.insertCell(0).innerHTML = "Roll Count";
bottomRow.insertCell(0).innerHTML = "Roll Result";
for(i = 0; i < rolls; i++) {
topRow.insertCell(i + 1).innerHTML = i + 1;
}
for(j = 0; j < rolls; j++) {
randomRoll = Math.floor(Math.random() * 8) + 1;
bottomRow.insertCell(j + 1).innerHTML = randomRoll;
}
} else if (die.includes("d10")) {
topRow = document.getElementById("d10-roll-results").insertRow(0);
bottomRow = document.getElementById("d10-roll-results").insertRow(1);
topRow.insertCell(0).innerHTML = "Roll Count";
bottomRow.insertCell(0).innerHTML = "Roll Result";
for(i = 0; i < rolls; i++) {
topRow.insertCell(i + 1).innerHTML = i + 1;
}
for(j = 0; j < rolls; j++) {
randomRoll = Math.floor(Math.random() * 10);
bottomRow.insertCell(j + 1).innerHTML = randomRoll;
}
} else if (die.includes("d12")) {
topRow = document.getElementById("d12-roll-results").insertRow(0);
bottomRow = document.getElementById("d12-roll-results").insertRow(1);
topRow.insertCell(0).innerHTML = "Roll Count";
bottomRow.insertCell(0).innerHTML = "Roll Result";
for(i = 0; i < rolls; i++) {
topRow.insertCell(i + 1).innerHTML = i + 1;
}
for(j = 0; j < rolls; j++) {
randomRoll = Math.floor(Math.random() * 12) + 1;
bottomRow.insertCell(j + 1).innerHTML = randomRoll;
}
} else if (die.includes("d20")) {
topRow = document.getElementById("d20-roll-results").insertRow(0);
bottomRow = document.getElementById("d20-roll-results").insertRow(1);
topRow.insertCell(0).innerHTML = "Roll Count";
bottomRow.insertCell(0).innerHTML = "Roll Result";
for(i = 0; i < rolls; i++) {
topRow.insertCell(i + 1).innerHTML = i + 1;
}
for(j = 0; j < rolls; j++) {
randomRoll = Math.floor(Math.random() * 20) + 1;
bottomRow.insertCell(j + 1).innerHTML = randomRoll;
}
}
}
首先,您应该 avoid inline handlers,它们有太多问题值得使用。使用 JavaScript 和 addEventListener
正确附加监听器。
单击按钮,导航至其父窗体或 div 以识别骰子的类型。然后,从父级 div,导航到 div 的 table 子级并填充它:
document.querySelector('#dice').addEventListener('click', (e) => {
if (!e.target.matches('button')) {
return;
}
e.preventDefault();
const { target } = e;
const div = target.closest('div');
const dieType = div.dataset.dieType;
const numDice = target.previousElementSibling.value;
const table = div.querySelector('table');
table.innerHTML += `
<tr>
<td>Roll Count</td>
${Array.from({ length: numDice }, (_, i) => `<td>${i + 1}</td>`).join('')}
</tr>
<tr>
<td>Roll Result</td>
${Array.from({ length: numDice }, () => `<td>${Math.floor(Math.random() * dieType) + 1}</td>`).join('')}
</tr>
`;
});
#dice table {
border-collapse: collapse;
}
#dice td {
border: 1px solid black;
padding: 4px;
}
#dice div {
padding: 10px 0 0;
}
<div>
<h1>Select the number of rolls for each dice</h1>
<div id="dice">
<div data-die-type="4">
<form>
<label><span>D4  </span><input type="number" min="0" max="10"><button>Confirm</button></label>
</form>
<div><table></table></div>
</div>
<hr />
<div data-die-type="6">
<form>
<label><span>D6  </span><input type="number" min="0" max="10"><button>Confirm</button></label>
</form>
<div><table></table></div>
</div>
<hr />
<div data-die-type="8">
<form>
<label><span>D8  </span><input type="number" min="0" max="10"><button>Confirm</button></label>
</form>
<div><table></table></div>
</div>
<hr />
<div data-die-type="10">
<form>
<label><span>D10</span><input type="number" min="0" max="10"><button>Confirm</button></label>
</form>
<div><table></table></div>
</div>
<hr />
<div data-die-type="12">
<form>
<label><span>D12</span><input type="number" min="0" max="10"><button>Confirm</button></label>
</form>
<div><table></table></div>
</div>
<hr />
<div data-die-type="20">
<form>
<label><span>D20</span><input type="number" min="0" max="10"><button>Confirm</button></label>
</form>
<div><table></table></div>
</div>
</div>
</div>
了解如何让您的 HTML 也变得更加 DRY - 不需要所有那些不同的 ID 和属性。
我制作了一个简单的 D&D 骰子滚动应用程序进行练习,发现其中有很多重复代码。不过,我找不到自己重构它的好方法。任何提示表示赞赏。公平警告,我是一个菜鸟,所以我已经知道它可能有比我知道的更多的问题。放心真的让我拥有。
https://jsfiddle.net/sakonexus/nd82qjec/
function calcRoll(e) {
let die = e.target.previousElementSibling.name;
let rolls = e.target.previousElementSibling.value;
let topRow = {};
let bottomRow = {};
let randomRoll = 0;
if (rolls == '') {
rolls = 0;
}
if (die.includes("d4")) {
topRow = document.getElementById("d4-roll-results").insertRow(0);
bottomRow = document.getElementById("d4-roll-results").insertRow(1);
topRow.insertCell(0).innerHTML = "Roll Count";
bottomRow.insertCell(0).innerHTML = "Roll Result";
for(i = 0; i < rolls; i++) {
topRow.insertCell(i + 1).innerHTML = i + 1;
}
for(j = 0; j < rolls; j++) {
randomRoll = Math.floor(Math.random() * 4) + 1;
bottomRow.insertCell(j + 1).innerHTML = randomRoll;
}
} else if (die.includes("d6")) {
topRow = document.getElementById("d6-roll-results").insertRow(0);
bottomRow = document.getElementById("d6-roll-results").insertRow(1);
topRow.insertCell(0).innerHTML = "Roll Count";
bottomRow.insertCell(0).innerHTML = "Roll Result";
for(i = 0; i < rolls; i++) {
topRow.insertCell(i + 1).innerHTML = i + 1;
}
for(j = 0; j < rolls; j++) {
randomRoll = Math.floor(Math.random() * 6) + 1;
bottomRow.insertCell(j + 1).innerHTML = randomRoll;
}
} else if (die.includes("d8")) {
topRow = document.getElementById("d8-roll-results").insertRow(0);
bottomRow = document.getElementById("d8-roll-results").insertRow(1);
topRow.insertCell(0).innerHTML = "Roll Count";
bottomRow.insertCell(0).innerHTML = "Roll Result";
for(i = 0; i < rolls; i++) {
topRow.insertCell(i + 1).innerHTML = i + 1;
}
for(j = 0; j < rolls; j++) {
randomRoll = Math.floor(Math.random() * 8) + 1;
bottomRow.insertCell(j + 1).innerHTML = randomRoll;
}
} else if (die.includes("d10")) {
topRow = document.getElementById("d10-roll-results").insertRow(0);
bottomRow = document.getElementById("d10-roll-results").insertRow(1);
topRow.insertCell(0).innerHTML = "Roll Count";
bottomRow.insertCell(0).innerHTML = "Roll Result";
for(i = 0; i < rolls; i++) {
topRow.insertCell(i + 1).innerHTML = i + 1;
}
for(j = 0; j < rolls; j++) {
randomRoll = Math.floor(Math.random() * 10);
bottomRow.insertCell(j + 1).innerHTML = randomRoll;
}
} else if (die.includes("d12")) {
topRow = document.getElementById("d12-roll-results").insertRow(0);
bottomRow = document.getElementById("d12-roll-results").insertRow(1);
topRow.insertCell(0).innerHTML = "Roll Count";
bottomRow.insertCell(0).innerHTML = "Roll Result";
for(i = 0; i < rolls; i++) {
topRow.insertCell(i + 1).innerHTML = i + 1;
}
for(j = 0; j < rolls; j++) {
randomRoll = Math.floor(Math.random() * 12) + 1;
bottomRow.insertCell(j + 1).innerHTML = randomRoll;
}
} else if (die.includes("d20")) {
topRow = document.getElementById("d20-roll-results").insertRow(0);
bottomRow = document.getElementById("d20-roll-results").insertRow(1);
topRow.insertCell(0).innerHTML = "Roll Count";
bottomRow.insertCell(0).innerHTML = "Roll Result";
for(i = 0; i < rolls; i++) {
topRow.insertCell(i + 1).innerHTML = i + 1;
}
for(j = 0; j < rolls; j++) {
randomRoll = Math.floor(Math.random() * 20) + 1;
bottomRow.insertCell(j + 1).innerHTML = randomRoll;
}
}
}
首先,您应该 avoid inline handlers,它们有太多问题值得使用。使用 JavaScript 和 addEventListener
正确附加监听器。
单击按钮,导航至其父窗体或 div 以识别骰子的类型。然后,从父级 div,导航到 div 的 table 子级并填充它:
document.querySelector('#dice').addEventListener('click', (e) => {
if (!e.target.matches('button')) {
return;
}
e.preventDefault();
const { target } = e;
const div = target.closest('div');
const dieType = div.dataset.dieType;
const numDice = target.previousElementSibling.value;
const table = div.querySelector('table');
table.innerHTML += `
<tr>
<td>Roll Count</td>
${Array.from({ length: numDice }, (_, i) => `<td>${i + 1}</td>`).join('')}
</tr>
<tr>
<td>Roll Result</td>
${Array.from({ length: numDice }, () => `<td>${Math.floor(Math.random() * dieType) + 1}</td>`).join('')}
</tr>
`;
});
#dice table {
border-collapse: collapse;
}
#dice td {
border: 1px solid black;
padding: 4px;
}
#dice div {
padding: 10px 0 0;
}
<div>
<h1>Select the number of rolls for each dice</h1>
<div id="dice">
<div data-die-type="4">
<form>
<label><span>D4  </span><input type="number" min="0" max="10"><button>Confirm</button></label>
</form>
<div><table></table></div>
</div>
<hr />
<div data-die-type="6">
<form>
<label><span>D6  </span><input type="number" min="0" max="10"><button>Confirm</button></label>
</form>
<div><table></table></div>
</div>
<hr />
<div data-die-type="8">
<form>
<label><span>D8  </span><input type="number" min="0" max="10"><button>Confirm</button></label>
</form>
<div><table></table></div>
</div>
<hr />
<div data-die-type="10">
<form>
<label><span>D10</span><input type="number" min="0" max="10"><button>Confirm</button></label>
</form>
<div><table></table></div>
</div>
<hr />
<div data-die-type="12">
<form>
<label><span>D12</span><input type="number" min="0" max="10"><button>Confirm</button></label>
</form>
<div><table></table></div>
</div>
<hr />
<div data-die-type="20">
<form>
<label><span>D20</span><input type="number" min="0" max="10"><button>Confirm</button></label>
</form>
<div><table></table></div>
</div>
</div>
</div>
了解如何让您的 HTML 也变得更加 DRY - 不需要所有那些不同的 ID 和属性。