You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用方向键在卡片元素间导航并解决.next is not a function报错

问题根因

你触发报错的核心原因有两个:

  1. 你代码里写的".card:focus"是普通字符串,不是DOM元素实例,自然没有next()、prev()方法,这两个方法本身也是jQuery的API,原生JS没有对应的同名方法。
  2. Lit组件默认开启Shadow DOM,直接用document.querySelector('.card')是找不到Shadow DOM内部的元素的,需要先拿到自定义元素实例再访问其shadowRoot。

修复步骤

1. 修改子组件,让卡片可聚焦

给卡片div添加tabindex="0"属性,使其支持键盘聚焦,同时可以添加聚焦状态样式优化体验:

// 子组件样式部分新增:focus状态
.card:focus {
  outline: 3px solid #4f46e5;
  outline-offset: 2px;
}

// render部分修改div
render() {
  const { name, image } = this;
  return html`
    <div class="card" tabindex="0">
      <p>${name}</p>
      <img src=${image} />
    </div>
  `;
}

2. 修改父组件的键盘监听逻辑

调整事件绑定逻辑,补全元素获取、边界处理和事件清理逻辑:

useEffect(() => {
  const handleKeydown = (e) => {
    if (e.key !== 'ArrowRight' && e.key !== 'ArrowLeft') return;

    // 先拿到所有卡片元素
    const allCardWrappers = Array.from(document.querySelectorAll('pokemon-card'));
    const allCards = allCardWrappers.map(wrapper => wrapper.shadowRoot.querySelector('.card'));
    if (allCards.length === 0) return;

    // 找到当前聚焦的卡片下标
    const currentIndex = allCards.findIndex(card => card === document.activeElement?.shadowRoot?.activeElement);

    let targetIndex;
    if (currentIndex === -1) {
      // 没有卡片聚焦时默认选中第一个
      targetIndex = 0;
    } else if (e.key === 'ArrowRight') {
      // 右方向键:到最后一个就切回第一个
      targetIndex = currentIndex + 1 >= allCards.length ? 0 : currentIndex + 1;
    } else {
      // 左方向键:到第一个就切回最后一个
      targetIndex = currentIndex - 1 < 0 ? allCards.length - 1 : currentIndex - 1;
    }

    allCards[targetIndex].focus();
    e.preventDefault();
  };

  document.addEventListener('keydown', handleKeydown);
  // 组件卸载时移除监听,避免内存泄漏
  return () => document.removeEventListener('keydown', handleKeydown);
}, []); // 空依赖数组,仅在组件挂载时绑定一次

内容的提问来源于stack exchange,提问作者coding1223322

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 15:18:04