You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何用jQuery动态添加含EJS的页面元素?附多选择器回库需求

我来一步步帮你搞定这个需求,从Express传递MySQL数据到EJS模板,到动态添加带唯一标识的选择器,再到把数据回存数据库,最后解决你提到的「动态添加包含EJS的页面元素」问题,全给你捋清楚:

解决方案分步指南

1. Express从MySQL取数据并传给EJS

首先得在Express里配置MySQL连接,查询到需要的选项数据后,通过render方法传递给EJS模板。这里用mysql2(支持Promise,写法更简洁)为例:

const express = require('express');
const mysql = require('mysql2/promise');
const app = express();

// MySQL连接配置
const dbConfig = {
  host: 'localhost',
  user: '你的数据库用户名',
  password: '你的数据库密码',
  database: '目标数据库名'
};

// 渲染页面的路由:查询数据并传给EJS
app.get('/dynamic-selectors', async (req, res) => {
  try {
    const connection = await mysql.createConnection(dbConfig);
    // 这里查询你需要作为选择器选项的数据
    const [options] = await connection.execute('SELECT id, name FROM your_options_table');
    await connection.end();

    // 传递数据给EJS,同时初始化选择器的起始索引
    res.render('selectors-page', { options, startIndex: 0 });
  } catch (err) {
    console.error('数据库查询失败:', err);
    res.status(500).send('服务器内部错误');
  }
});

app.listen(3000, () => console.log('服务器运行在 http://localhost:3000'));

2. EJS模板渲染初始选择器

在EJS里,我们先渲染第一个选择器,给它设置唯一的idname(用数组格式的name,方便后端批量接收数据),同时把MySQL数据存到前端全局变量里,供后续jQuery动态生成选择器使用:

<!DOCTYPE html>
<html>
<head>
  <title>动态选择器示例</title>
  <script src="https://code.jquery.com/jquery-3.6.4.min.js"></script>
</head>
<body>
  <!-- 把MySQL选项数据存到全局变量,供jQuery调用 -->
  <script>
    window.selectOptions = <%- JSON.stringify(options) %>;
  </script>

  <!-- 选择器容器 -->
  <div id="selectors-container">
    <!-- 初始选择器 -->
    <div class="selector-group" data-index="<%= startIndex %>">
      <label for="selector-<%= startIndex %>">选择项:</label>
      <select id="selector-<%= startIndex %>" name="selectors[<%= startIndex %>][option_id]">
        <% options.forEach(opt => { %>
          <option value="<%= opt.id %>"><%= opt.name %></option>
        <% }) %>
      </select>
      <button class="remove-btn">删除</button>
    </div>
  </div>

  <!-- 添加选择器按钮 -->
  <button id="add-selector-btn">添加更多选择器</button>

  <!-- 表单提交:把所有选择器数据回传给后端 -->
  <form action="/save-selections" method="POST">
    <div id="selectors-container"></div>
    <button type="submit">保存所有选择</button>
  </form>

  <script>
    // 这里放jQuery动态操作代码,下面会写
  </script>
</body>
</html>

3. jQuery动态添加带唯一标识的选择器

用jQuery实现点击按钮新增选择器,每次新增时递增索引值,保证每个选择器的idname唯一。这里直接用之前存在全局变量里的选项数据生成下拉框:

$(document).ready(function() {
  // 初始化当前索引:从初始选择器的index+1开始
  let currentIndex = parseInt($('.selector-group:last').data('index')) + 1;

  // 绑定「添加选择器」按钮事件
  $('#add-selector-btn').click(function() {
    // 创建新的选择器组容器
    const group = $('<div>').addClass('selector-group').data('index', currentIndex);

    // 创建标签
    const label = $('<label>').attr('for', `selector-${currentIndex}`).text('选择项:');

    // 创建下拉选择器,设置唯一id和name
    const select = $('<select>').attr({
      id: `selector-${currentIndex}`,
      name: `selectors[${currentIndex}][option_id]`
    });

    // 从全局变量加载选项
    window.selectOptions.forEach(opt => {
      select.append($('<option>').attr('value', opt.id).text(opt.name));
    });

    // 创建删除按钮,绑定删除事件
    const removeBtn = $('<button>').addClass('remove-btn').text('删除').click(function() {
      $(this).parent().remove();
      // 注:如果不需要严格连续的索引,删除后不用重新整理;后端接收时会自动忽略缺失的索引
    });

    // 组装元素并添加到容器
    group.append(label).append(select).append(removeBtn);
    $('#selectors-container').append(group);

    // 索引递增
    currentIndex++;
  });

  // 绑定删除按钮事件(用事件委托,兼容动态添加的元素)
  $(document).on('click', '.remove-btn', function() {
    $(this).parent().remove();
  });
});

4. 后端接收并保存选择器数据

先配置Express解析表单数据,然后在路由里接收所有选择器的数据,批量插入数据库:

// 配置解析表单数据
app.use(express.urlencoded({ extended: true }));

// 处理表单提交的路由
app.post('/save-selections', async (req, res) => {
  const selectors = req.body.selectors;
  // 把对象格式的选择器数据转成二维数组,方便批量插入
  const selectionValues = Object.values(selectors).map(item => [item.option_id]);

  try {
    const connection = await mysql.createConnection(dbConfig);
    // 批量插入数据(用占位符防止SQL注入)
    await connection.query('INSERT INTO your_target_table (option_id) VALUES ?', [selectionValues]);
    await connection.end();

    res.send('所有选择已成功保存!');
  } catch (err) {
    console.error('保存失败:', err);
    res.status(500).send('保存数据时出错');
  }
});

关于「用jQuery动态添加包含EJS的页面元素」的说明

要注意:EJS是服务器端渲染引擎,客户端的jQuery无法直接解析EJS语法(因为EJS代码在服务器已经编译成HTML了)。如果你的动态元素需要用到EJS的复杂逻辑(比如循环、条件判断),有两种可行方案:

方案1:提前传数据到前端,用JS生成元素

就是我们前面用的方式:把需要的业务数据传到前端存在全局变量里,然后用jQuery根据数据生成HTML元素。这种方式性能好,是最常用的方案。

方案2:AJAX请求后端渲染好的EJS片段

如果动态元素的逻辑非常复杂,必须用EJS处理,可以做一个后端接口,接收参数后渲染EJS片段,前端用AJAX获取并插入页面:

后端接口:

app.get('/selector-fragment', (req, res) => {
  const index = req.query.index;
  // 这里可以直接用之前查询好的options,或者重新查询
  res.render('selector-fragment', { options: yourOptions, index });
});

EJS片段模板(selector-fragment.ejs):

<div class="selector-group" data-index="<%= index %>">
  <label for="selector-<%= index %>">选择项:</label>
  <select id="selector-<%= index %>" name="selectors[<%= index %>][option_id]">
    <% options.forEach(opt => { %>
      <option value="<%= opt.id %>"><%= opt.name %></option>
    <% }) %>
  </select>
  <button class="remove-btn">删除</button>
</div>

前端jQuery修改:

$('#add-selector-btn').click(function() {
  $.get(`/selector-fragment?index=${currentIndex}`, function(html) {
    $('#selectors-container').append(html);
    currentIndex++;
  });
});

这种方式适合复杂场景,但会多一次AJAX请求,需要根据实际需求权衡。


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

火山引擎 最新活动