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

.NET Core开发者寻求Razor页面多记录录入的JavaScript库推荐

适合Razor页面多记录录入的JavaScript工具推荐

针对Razor页面中批量录入多条记录的需求,推荐几个实用且易上手的JS工具/方案,完全适配.NET Core的模型绑定逻辑:

1. 原生jQuery轻量实现(无额外依赖)

如果不想引入复杂框架,基于jQuery就能快速实现动态添加/删除表单行的功能,核心是利用Razor支持的索引式模型绑定(比如MenuItems[0].Price这类命名格式)。

示例代码:

<!-- 隐藏的模板行 -->
<div class="menu-item-template d-none">
  <div class="row mb-2">
    <input type="text" name="MenuItems[__INDEX__].MenuName" class="form-control col" placeholder="菜单名称">
    <input type="number" name="MenuItems[__INDEX__].Price" class="form-control col" placeholder="价格">
    <textarea name="MenuItems[__INDEX__].Description" class="form-control col" placeholder="描述"></textarea>
    <button type="button" class="btn btn-danger col-auto remove-row">删除</button>
  </div>
</div>

<!-- 表单容器 -->
<div id="menu-container">
  <!-- 初始化第一行 -->
  <div class="row mb-2">
    <input type="text" name="MenuItems[0].MenuName" class="form-control col" placeholder="菜单名称">
    <input type="number" name="MenuItems[0].Price" class="form-control col" placeholder="价格">
    <textarea name="MenuItems[0].Description" class="form-control col" placeholder="描述"></textarea>
    <button type="button" class="btn btn-danger col-auto remove-row">删除</button>
  </div>
</div>
<button type="button" id="add-row" class="btn btn-primary mt-2">添加菜单</button>
$(function() {
  let currentIndex = 1;
  
  // 添加新行
  $('#add-row').click(function() {
    const templateHtml = $('.menu-item-template').html().replace(/__INDEX__/g, currentIndex);
    $('#menu-container').append(templateHtml);
    currentIndex++;
  });

  // 删除行并重新索引(可选,不影响绑定但更规范)
  $(document).on('click', '.remove-row', function() {
    $(this).closest('.row').remove();
    // 重新整理所有行的索引
    $('#menu-container .row').each(function(i) {
      $(this).find('input, textarea').each(function() {
        const newName = $(this).attr('name').replace(/\[\d+\]/, `[${i}]`);
        $(this).attr('name', newName);
      });
    });
    currentIndex = $('#menu-container .row').length;
  });
});

优势:零额外依赖,直接适配Razor模型绑定,代码简单易懂,适合快速实现基础需求。

2. Vue.js(数据驱动,更整洁)

如果需要更优雅的表单管理,可以引入Vue.js的CDN,用双向绑定批量维护记录数组,提交时直接序列化数据给后端,无需手动处理DOM和命名。

示例代码:

<div id="menuApp" class="container">
  <div v-for="(item, idx) in menuItems" :key="idx" class="row mb-2">
    <input v-model="item.MenuName" type="text" class="form-control col" placeholder="菜单名称">
    <input v-model.number="item.Price" type="number" class="form-control col" placeholder="价格">
    <textarea v-model="item.Description" class="form-control col" placeholder="描述"></textarea>
    <button @click="removeItem(idx)" class="btn btn-danger col-auto">删除</button>
  </div>
  <button @click="addItem" class="btn btn-primary mt-2">添加菜单</button>
  <button @click="submitForm" class="btn btn-success mt-2 ms-2">提交</button>
</div>

<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script>
  const app = Vue.createApp({
    data() {
      return {
        menuItems: [{ MenuName: '', Price: 0, Description: '' }]
      }
    },
    methods: {
      addItem() {
        this.menuItems.push({ MenuName: '', Price: 0, Description: '' });
      },
      removeItem(idx) {
        this.menuItems.splice(idx, 1);
      },
      async submitForm() {
        // 方式1:转为FormData适配Razor模型绑定
        const formData = new FormData();
        this.menuItems.forEach((item, idx) => {
          formData.append(`MenuItems[${idx}].MenuName`, item.MenuName);
          formData.append(`MenuItems[${idx}].Price`, item.Price);
          formData.append(`MenuItems[${idx}].Description`, item.Description);
        });
        await fetch('/Menu/SaveBatch', { method: 'POST', body: formData });

        // 方式2:提交JSON(后端用[FromBody]接收)
        // await fetch('/Menu/SaveBatchJson', {
        //   method: 'POST',
        //   headers: { 'Content-Type': 'application/json' },
        //   body: JSON.stringify(this.menuItems)
        // });
      }
    }
  }).mount('#menuApp');
</script>

优势:数据驱动,代码结构清晰,支持轻松扩展表单验证(比如搭配VeeValidate),适合稍复杂的录入场景。

3. Alpine.js(超轻量声明式工具)

如果想要比Vue更轻量的方案,Alpine.js是绝佳选择——体积仅7KB,无需编译,语法接近原生JS,直接在Razor页面中使用。

示例代码:

<div x-data="{ menuItems: [{ MenuName: '', Price: 0, Description: '' }] }" class="container">
  <template x-for="(item, idx) in menuItems" :key="idx">
    <div class="row mb-2">
      <input x-model="item.MenuName" type="text" class="form-control col" placeholder="菜单名称">
      <input x-model.number="item.Price" type="number" class="form-control col" placeholder="价格">
      <textarea x-model="item.Description" class="form-control col" placeholder="描述"></textarea>
      <button @click="menuItems.splice(idx, 1)" class="btn btn-danger col-auto">删除</button>
    </div>
  </template>
  <button @click="menuItems.push({ MenuName: '', Price: 0, Description: '' })" class="btn btn-primary mt-2">添加菜单</button>
  
  <form @submit.prevent="submit" class="mt-2">
    <input type="hidden" x-ref="jsonData" name="MenuItemsJson">
    <button type="submit" class="btn btn-success">提交</button>
  </form>
</div>

<script defer src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js"></script>
<script>
  document.addEventListener('alpine:init', () => {
    Alpine.data('menuForm', () => ({
      submit() {
        this.$refs.jsonData.value = JSON.stringify(this.menuItems);
        this.$el.submit();
      }
    }));
  });
</script>

后端可直接接收string MenuItemsJson参数,反序列化为List<MenuItem>即可。
优势:几乎无学习成本,体积极小,不影响页面加载速度,适合追求轻量的场景。


通用注意事项

  • 后端模型需定义为List<MenuItem>类型,Razor会自动识别索引式命名的表单字段完成绑定;
  • 可结合HTML5原生验证或后端数据注解验证,确保录入数据的合法性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 04:45:29