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

拆分JS文件后出现Alpine Expression Error: board未定义求助

Alpine.js 拆分代码后报错:board is not defined

将Tile类迁移至Tile.js、游戏数据从app.js移至game.js后出现标题中的错误,所有JS代码在同一文件时运行正常,拆分后报错,已排除常见语法等简单问题。

错误信息

Alpine Expression Error: board is not defined
Expression: "board"
HTMLTemplateElement{attributes: {…}, innerHTML: "\n <div class="row">\n <template x-for="tile in row">\n <div class="tile" x-text="tile.letter"><…", nodeType: 1, tagName: "template"}

相关代码

index.html

<html>
  <head>
    <base href="/" target="_blank" />
    <link rel="stylesheet" href="./styles.scss" />
    <script src="//unpkg.com/alpinejs" defer></script>
    <script type="module" src="./app.js"></script>
  </head>
  <body>
    <div id="game" x-data="game" @keyup.window="onKeyPress($event.key)">
      <template x-for="row in board">
        <div class="row">
          <template x-for="tile in row">
            <div class="tile" x-text="tile.letter"></div>
          </template>
        </div>
      </template>
    </div>
  </body>
</html>

app.js

import game from './game';

document.addEventListener('alpine:init', () => {
  Alpine.data('game', () => game);
});

game.js

import Tile from './Tile';

export default {
  guessesAllowed: 5,
  wordLength: 5,
  currentRowIndex: 0,

  init() {
    this.board = Array.from({ length: this.guessesAllowed }, () => {
      return Array.from({ length: this.wordLength }, () => new Tile());
    });
  },

  onKeyPress(key) {
    if (/^[A-z]$/.test(key)) {
      this.fillTile(key);
    }
  },

  fillTile(key) {
    for (let tile of this.currentRow()) {
      if (!tile.letter) {
        tile.fill(key);
        break;
      }
    }

    if (this.currentTileIndex === this.wordLength - 1) {
      this.currentRowIndex++;
      this.currentTileIndex = 0;
    } else {
      this.currentTileIndex++;
    }
  },

  currentRow() {
    return this.board[this.currentRowIndex];
  },
};

Tile.js

export default class Tile {
  letter = '';
  status = ''; // 'correct', 'incorrect', 'empty'
  
  fill(key) {
      this.letter = key.toUpperCase();
      this.status = 'filled';
  }
  
  empty() {
      this.letter = '';
      this.status = 'empty';
  }
}

问题原因及修复方案

核心原因

  1. 模板渲染时机早于board初始化:Alpine.js组件挂载时会立即渲染模板,而board仅在init()方法中赋值,此时模板访问board时该属性还不存在,导致报错。
  2. 共享实例导致状态异常:直接将导出的game对象传给Alpine.data,所有组件实例会共享同一个对象,后续操作可能引发不可预期的问题。
  3. 缺失currentTileIndex初始值:代码中使用了currentTileIndex但未初始化,后续fillTile方法会报错。

修复步骤

  1. 给board和currentTileIndex添加初始值
    修改game.js,在默认导出对象中补充初始属性:

    export default {
      guessesAllowed: 5,
      wordLength: 5,
      currentRowIndex: 0,
      currentTileIndex: 0, // 补上缺失的初始值
      board: [], // 给board设置初始空数组
      // ... 原init及其他方法不变
    };
    
  2. 改为返回新对象的函数,避免实例共享
    修改game.js为导出函数,确保每次调用都生成新的组件状态对象:

    import Tile from './Tile';
    
    export default () => ({
      guessesAllowed: 5,
      wordLength: 5,
      currentRowIndex: 0,
      currentTileIndex: 0,
      board: [],
    
      init() {
        this.board = Array.from({ length: this.guessesAllowed }, () => {
          return Array.from({ length: this.wordLength }, () => new Tile());
        });
      },
    
      onKeyPress(key) {
        if (/^[A-z]$/.test(key)) {
          this.fillTile(key);
        }
      },
    
      fillTile(key) {
        for (let tile of this.currentRow()) {
          if (!tile.letter) {
            tile.fill(key);
            break;
          }
        }
    
        if (this.currentTileIndex === this.wordLength - 1) {
          this.currentRowIndex++;
          this.currentTileIndex = 0;
        } else {
          this.currentTileIndex++;
        }
      },
    
      currentRow() {
        return this.board[this.currentRowIndex];
      },
    });
    
  3. 调整app.js的调用(可选,若上面修改game.js为函数则直接用)
    若保持game.js为对象,app.js需改为每次返回新对象:

    import game from './game';
    
    document.addEventListener('alpine:init', () => {
      Alpine.data('game', () => ({...game})); // 解构生成新对象
    });
    

完成以上修改后,模板渲染时board有初始空数组不会报错,init()执行后会替换为正确的棋盘数据,同时每个组件实例拥有独立状态,功能可正常运行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 15:35:39