动态生成表格行并基于条形码异步填充数据的完整实现

本文介绍如何使用原生 javascript 和 php 实现:页面加载时渲染含输入框的首行表格,用户输入条形码后,通过 ajax 异步查询数据库并填充对应商品信息,同时自动追加下一行空白输入行。全程无需 jquery,代码简洁可扩展。

要实现“逐行添加 + 条形码驱动数据填充”的交互式表格,核心在于三步协同:HTML 结构初始化 → 用户输入触发 AJAX 请求 → 后端响应后更新当前行 + 动态插入新行。下面以专业、可落地的方式逐步说明。

✅ 1. 前端 HTML 与初始结构

确保表格拥有唯一 ID(如 id="products"),首行使用 绑定 onchange 事件,并为后续动态行预留语义化 ID(如 product1、amount1):

barcode product amount price
⚠️ 注意:onchange 在用户失焦时触发(更稳妥);若需实时响应,可用 oninput + 防抖,但需自行处理重复请求。

✅ 2. 原生 JavaScript 核心逻辑(无 jQuery)

以下函数构成闭环流程:

  • onBarcodeChange(id):接收行序号,发起 AJAX 请求,填充本行数据,并调用 addTableRow() 创建下一行;
  • addTableRow(id):动态创建新 ,含带 onchange 的输入框及空单元格;
  • 使用 fetch() 替代过时的 XMLHttpRequest,更现代、简洁。
  • async function onBarcodeChange(id) {
      const input = document.querySelector(`#barcode${id} input`) || 
                    document.querySelector(`tr:nth-child(${id}) td:first-child input`);
      const barcode = input?.value.trim();
      if (!barcode) return;
    
      try {
        // ? 发起 AJAX 请求(PHP 后端接口)
        const response = await fetch('get_product.php', {
          method: 'POST',
          headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
          body: `barcode=${encodeURIComponent(barcode)}`
        });
    
        if (!response.ok) throw new Error('Network response was not ok');
    
        const data = await response.json();
    
        // ✅ 填充当前行(根据 ID 定位)
        document.getElement

    ById(`product${id}`).textContent = data.product || '-'; document.getElementById(`amount${id}`).textContent = data.amount || '0'; document.getElementById(`price${id}`).textContent = `${data.price || '0'} $`; // ➕ 追加下一行(ID 自增) addTableRow(id + 1); } catch (err) { alert(`Error loading product: ${err.message}`); console.error(err); } } function addTableRow(id) { const row = document.createElement('tr'); // 第一列:带事件的输入框 const barcodeCell = document.createElement('td'); barcodeCell.style.textAlign = 'center'; const input = document.createElement('input'); input.type = 'text'; input.placeholder = 'Enter barcode'; input.id = `barcode${id}`; input.onchange = () => onBarcodeChange(id); barcodeCell.appendChild(input); // 其余三列:空单元格(带 ID 便于后续填充) const cellNames = ['product', 'amount', 'price']; const otherCells = cellNames.map(name => { const td = document.createElement('td'); td.id = `${name}${id}`; td.style.textAlign = 'center'; return td; }); // 拼接整行 [barcodeCell, ...otherCells].forEach(td => row.appendChild(td)); document.getElementById('products').querySelector('tbody').appendChild(row); input.focus(); // 自动聚焦新输入框,提升体验 }

    ✅ 3. PHP 后端接口(get_product.php)

    该文件接收条形码,查询 MySQL 并返回 JSON:

     'Missing barcode']);
        exit;
    }
    
    $barcode = trim($_POST['barcode']);
    
    // ✅ 使用 PDO(推荐)或 mysqli —— 此处以 PDO 为例
    try {
        $pdo = new PDO("mysql:host=localhost;dbname=your_db", "username", "password");
        $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    
        $stmt = $pdo->prepare("SELECT product_name, amount, price FROM products WHERE barcode = ?");
        $stmt->execute([$barcode]);
        $row = $stmt->fetch(PDO::FETCH_ASSOC);
    
        if ($row) {
            echo json_encode([
                'product' => htmlspecialchars($row['product_name']),
                'amount'  => (int)$row['amount'],
                'price'   => (float)$row['price']
            ]);
        } else {
            echo json_encode(['product' => 'Not found', 'amount' => 0, 'price' => 0]);
        }
    } catch (PDOException $e) {
        error_log('DB Error: ' . $e->getMessage());
        http_response_code(500);
        echo json_encode(['error' => 'Database error']);
    }
    ?>

    ✅ 安全提示:务必使用预处理语句防止 SQL 注入;输出前用 htmlspecialchars() 防 XSS。

    ✅ 4. 补充建议与最佳实践

    • 用户体验优化:在 onBarcodeChange 开始时禁用输入框、显示 loading 文本,响应后恢复;
    • 错误处理强化:对空结果、网络超时、HTTP 错误码做分层提示;
    • 键盘支持:监听 Enter 键提交(input.addEventListener('keypress', e => e.key === 'Enter' && e.target.dispatchEvent(new Event('change'))));
    • 性能考虑:若单页行数较多(>50),建议虚拟滚动或分页,避免 DOM 过载。

    至此,你已拥有一套轻量、安全、可维护的“扫码即填表”解决方案——完全基于原生技术栈,零第三方依赖,可直接集成到现有 PHP 项目中。