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

Vue.js二级嵌套表单与复选框:JSON与REST API交互问题

实现Vue.js嵌套表单与分组复选框功能

看起来你需要完成一个带二级嵌套(按钮下的分组选择)的表单,还要从API拉取分组列表并通过复选框关联,最后提交JSON到REST API。我帮你把代码补全并梳理清楚逻辑:

1. 完善组件逻辑(Script部分)

首先我们需要在created钩子中调用API获取分组列表,补全删除按钮的逻辑,同时处理分组复选框的选中状态绑定:

<script>
export default {
  data () {
    return {
      line: {
        name: '',
        buttons: [{ 
          name: '', 
          state: false, 
          is_reported: '',
          // 新增:存储选中的分组名称,方便后续转换为提交格式
          selectedGroups: []
        }]
      },
      assignmentGroupsList: [] // 存储从API获取的分组列表
    }
  },
  created() {
    // 页面加载时自动拉取分组列表
    this.fetchAssignmentGroups()
  },
  methods: {
    // 调用API获取分组列表
    async fetchAssignmentGroups() {
      try {
        // 替换成你的实际API地址
        const response = await fetch('/api/assignment-groups')
        this.assignmentGroupsList = await response.json()
      } catch (error) {
        console.error('获取分组列表失败:', error)
      }
    },
    // 添加新的按钮配置项
    addButton () {
      this.line.buttons.push({ 
        name: '', 
        state: false, 
        is_reported: '',
        selectedGroups: []
      })
    },
    // 删除指定索引的按钮项
    deleteButton(index) {
      this.line.buttons.splice(index, 1)
    },
    // 切换分组复选框的选中状态
    toggleGroupSelection(buttonIndex, groupName) {
      const targetButton = this.line.buttons[buttonIndex]
      const groupIndex = targetButton.selectedGroups.indexOf(groupName)
      
      if (groupIndex > -1) {
        // 已选中,取消选择
        targetButton.selectedGroups.splice(groupIndex, 1)
      } else {
        // 未选中,添加选择
        targetButton.selectedGroups.push(groupName)
      }
    },
    // 提交表单到REST API
    async submitForm() {
      // 整理成后端需要的JSON格式:把选中的分组转换为对象数组
      const submitData = {
        ...this.line,
        buttons: this.line.buttons.map(button => ({
          ...button,
          assignmentGroups: button.selectedGroups.map(name => ({ name }))
        }))
      }
      
      try {
        // 替换成你的提交API地址
        const response = await fetch('/api/submit-form', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json'
          },
          body: JSON.stringify(submitData)
        })
        
        if (response.ok) {
          alert('表单提交成功!')
          // 提交成功后重置表单
          this.resetForm()
        } else {
          throw new Error('提交请求未通过')
        }
      } catch (error) {
        console.error('表单提交失败:', error)
        alert('表单提交失败,请稍后重试')
      }
    },
    // 重置表单到初始状态
    resetForm() {
      this.line = {
        name: '',
        buttons: [{ 
          name: '', 
          state: false, 
          is_reported: '',
          selectedGroups: []
        }]
      }
    }
  }
}
</script>

2. 编写模板(Template部分)

接下来是对应的HTML模板,实现嵌套表单的渲染和复选框交互:

<template>
  <div class="form-container">
    <h2>配置表单</h2>
    
    <!-- 主名称输入框 -->
    <div class="form-group">
      <label>主名称:</label>
      <input 
        v-model="line.name" 
        type="text" 
        placeholder="输入主名称"
        required
      >
    </div>

    <!-- 按钮配置区域 -->
    <div class="buttons-section">
      <h3>按钮配置列表</h3>
      <button @click="addButton" class="add-btn">添加新按钮</button>
      
      <!-- 遍历渲染每个按钮项 -->
      <div v-for="(button, btnIndex) in line.buttons" :key="btnIndex" class="button-item">
        <div class="button-header">
          <span>按钮 {{ btnIndex + 1 }}</span>
          <button @click="deleteButton(btnIndex)" class="delete-btn">删除</button>
        </div>
        
        <!-- 按钮基础信息输入 -->
        <div class="form-group">
          <label>按钮名称:</label>
          <input 
            v-model="button.name" 
            type="text" 
            placeholder="输入按钮名称"
            required
          >
        </div>
        
        <div class="form-group">
          <label>启用状态:</label>
          <input v-model="button.state" type="checkbox">
          <span>{{ button.state ? '已启用' : '已禁用' }}</span>
        </div>
        
        <div class="form-group">
          <label>是否上报:</label>
          <select v-model="button.is_reported">
            <option value="">请选择</option>
            <option value="yes">是</option>
            <option value="no">否</option>
          </select>
        </div>
        
        <!-- 分组选择复选框区域 -->
        <div class="groups-selection">
          <label>关联分组:</label>
          <div class="group-checkboxes">
            <div v-for="group in assignmentGroupsList" :key="group.name" class="checkbox-item">
              <input 
                type="checkbox"
                :checked="button.selectedGroups.includes(group.name)"
                @change="toggleGroupSelection(btnIndex, group.name)"
              >
              <span>{{ group.name }}</span>
            </div>
          </div>
        </div>
      </div>
    </div>

    <!-- 提交按钮(未填必填项时禁用) -->
    <button 
      @click="submitForm" 
      class="submit-btn" 
      :disabled="!line.name || line.buttons.some(btn => !btn.name)"
    >
      提交表单
    </button>
  </div>
</template>

3. 可选:添加基础样式(Style部分)

为了让表单布局更清晰,补充一些简单的CSS:

<style scoped>
.form-container {
  max-width: 800px;
  margin: 20px auto;
  padding: 20px;
  border: 1px solid #eee;
  border-radius: 8px;
}
.form-group {
  margin-bottom: 15px;
}
.form-group label {
  display: block;
  margin-bottom: 5px;
  font-weight: 500;
}
.form-group input, .form-group select {
  width: 100%;
  padding: 8px;
  border: 1px solid #ddd;
  border-radius: 4px;
  box-sizing: border-box;
}
.buttons-section {
  margin: 20px 0;
  padding: 15px;
  background-color: #f8f9fa;
  border-radius: 8px;
}
.button-item {
  margin: 15px 0;
  padding: 15px;
  border: 1px solid #ddd;
  border-radius: 8px;
}
.button-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 15px;
}
.add-btn, .delete-btn, .submit-btn {
  padding: 8px 16px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}
.add-btn {
  background-color: #28a745;
  color: white;
}
.delete-btn {
  background-color: #dc3545;
  color: white;
}
.submit-btn {
  background-color: #007bff;
  color: white;
  font-size: 16px;
}
.submit-btn:disabled {
  background-color: #6c757d;
  cursor: not-allowed;
}
.group-checkboxes {
  display: flex;
  flex-wrap: wrap;
  gap: 15px;
  margin-top: 8px;
}
.checkbox-item {
  display: flex;
  align-items: center;
  gap: 5px;
}
</style>

关键逻辑说明

  • 分组列表拉取:在组件创建时自动调用API获取分组,存储到assignmentGroupsList供复选框渲染使用
  • 嵌套表单管理:通过v-for遍历按钮数组实现动态新增/删除按钮项,每个按钮独立维护自己的选中分组
  • 复选框状态绑定:用selectedGroups数组记录每个按钮选中的分组,通过includes判断选中状态,toggleGroupSelection方法处理选中/取消逻辑
  • 提交数据转换:提交前将selectedGroups数组转换为后端需要的assignmentGroups对象数组格式,确保和API要求的JSON结构一致

这样整个表单就能完整实现你需要的功能啦~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 12:06:06