思路:首先找到当前current方格在网格中对应的横纵坐标x和y,再根据按键移动方向控制x和y的变化,尤其注意边界条件,即上下和左右的边界调整。其中找到横纵坐标x和y,使用的方法是,首先找到所有tr,并遍历tr是否包含current,如果是则锁定在哪一行即纵坐标,接着再找到该tr内的所有td,并遍历td是否等于current,如果是则锁定在哪一列即横坐标,注意querySelectorAll得到的是伪数组,需要使用Array.from转换为真数组。
<body>
<div id="jsContainer">
<table class="game">
<tbody>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td class="current"></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
</div>
<script type="text/javascript">
function bind() {
const con = document.getElementById("jsContainer")
const rows=con.querySelectorAll('tr')
const cols=rows[0].querySelectorAll('td')
document.onkeydown = event => {
if (!event) return;
var code = event.keyCode || '';
if (!{'37': 1, '38': 1, '39': 1, '40': 1}[code]) return;
event.preventDefault && event.preventDefault();
//TODO: 请实现按键控制
const cur=con.querySelector('.current')
let x=0
let y=0
// 找到cur对应的横纵坐标 y是哪一行即纵 x是哪一列即横
Array.from(rows).forEach((tr,index)=>{
if(tr.contains(cur))
{
y=index
Array.from(tr.querySelectorAll('td')).forEach((td,i)=>{
if(td===cur)
{
x=i
}
})
}
})
//上
if(Number(code)===38)
{
if(y===0)
y=rows.length-1
else
y--
}
//下
else if(Number(code)===40)
{
if(y===rows.length-1)
y=0
else
y++
}
//左
else if(Number(code)===37)
{
if(x===0)
x=cols.length-1
else
x--
}
//右
else if(Number(code)===39)
{
if(x===cols.length-1)
x=0
else
x++
}
cur.classList.remove('current')
rows[y].querySelectorAll('td')[x].classList.add('current')
};
}
bind()
</script>
</body>
总结:在javascript中,判断父子节点的包含关系以及寻找父子节点,是一个频繁使用的事情,此处特意总结一下以便后续复习。parentNode属性用于获取当前节点的父节点;childNodes属性用于获取当前节点的所有子节点列表;children属性用于获取当前节点的所有子节点元素列表(不包含文本节点和注释节点);firstChild属性用于获取当前节点的第一个子节点;lastChild属性用于获取当前节点的最后一个子节点;firstElement属性用于获取当前节点的第一个子元素节点;lastElement属性用于获取当前节点的最后一个子元素节点;nextSibling属性用于获取当前节点的下一个兄弟节点;previousSibling属性用于获取当前节点的上一个兄弟节点;contains方法用于判断当前节点是否是另一个节点的后代节点;
<div id="parent">
<p>这是一个段落</p>
文本节点
<span>这是一个span元素</span>
<!-- 这是一个注释节点 -->
</div>
var parent = document.getElementById("parent");
var childNodesList = parent.childNodes;
console.log(childNodesList.length); // 输出:4,包括文本节点、元素节点和注释节点
var childrenList = parent.children;
console.log(childrenList.length); // 输出:2,只包括元素节点,不包括文本节点和注释节点
console.log(childNodesList[0].nodeType); // 输出:1,元素节点
console.log(childNodesList[1].nodeType); // 输出:3,文本节点
console.log(childNodesList[3].nodeType); // 输出:8,注释节点
注意:childNodesList包含了父节点<div>下的所有子节点,包括文本节点、元素节点和注释节点,而childrenList只包含了元素节点<p>和<span>。通过nodeType属性可对各个节点类型进行判断,其中1表示元素节点,3表示文本节点,8表示注释节点。



京公网安备 11010502036488号