首页 > 技术文章 > vue elementui 中使用 form submit 和 axios 提交数据

ymdi 2020-11-25 11:23 原文

有一个通用的 form 组件,内部渲染了海量的 form 元素,有input、checkbox、select,radio 等。

这样一个组件,我肯定不能手动排版啊。
果断跟后台商量一下,通过后台返回的 json 数据来动态渲染,另外一些不方便放回的,本地写个json。

写完美滋滋。

一提交数据,发现后端验证不通过,杀人.jpg

打开 network,看看何方妖孽在兴风作浪?
发现由于 vue 中,所有的表单数据都会定义在 data 函数的 form属性下

data(){
	return {
		form: {
			username: '',
			userRole: '',
			ifLoginForbid: false
		}
	}
}

导致 form 时把所有的表单的数据一起提交了。

因为页面通过各种 v-if 来判断显示和隐藏元素了,但提交的时候不好进行判断。
手动去写各种 if 条件判断来提交哪些数据,过滤哪些数据(太多,笨重不好维护)

所以就想到使用 form 自带的 submit,嘿嘿嘿嘿 。

因为 form 自带的 submit 是根据页面存在的元素来提交数据,所以完美的解决我的需求。

那么,问题是在 vue 中如何使用 form 的 submit 来获取数据呢?

首先,我们有一个 form 表单,表单所有的元素都有 name 属性。

<form action="####" @submit.prevent="submitform" ref="form">
	<el-input type="text" v-model="username" name="username">
	<el-select v-model="userRole" placeholder="请选择" name=""userRole>
	    <el-option
	      v-for="item in userRoleList"
	      :key="item.value"
	      :label="item.label"
	      :value="item.value">
	    </el-option>
	</el-select>
	<el-checkbox v-model="ifLoginForbid" name="ifLoginForbid">禁止登录?</el-checkbox>
	<input type="submit" value="" v-show="false" @click="submitform">
</form>

然后,通过手动调用 this.submitform() 来获取 form 数据

...
methods: {
	submitform(){
		  // 通过 FormData 取得相应的 form 上的数据
		  const formData = new FormData(this.$refs['form'])
	      const data = {}
	      // entries返回一个 iterator对象 ,此对象可以遍历访问FormData中的键值对
	      for (let [key, val] of formData.entries()) {
	        console.log([key, val] )
	        Object.assign(data, { [key]: val })
	      }
	      return data // {username: ''username'', userRole: 1}
	}
}
...

疑?? 我的 ifLoginForbid 去了哪里~~打印下看看

console.log(formData.getKey('ifLoginForbid'))

是个 null

查看下元素,发现 checkbox 是未选中的状态,所以 formData 根本没有拿到这个数据。那我选中后测试下?

{username: ''username'', userRole: 1, ifLoginForbid: ''}

汰!不科学啊,居然是个空字符!

再次查看元素,看看是哪个刁民又在害我。发现选中状态的 el-checkbox 里的 input 是这样:

<input type="checkbox" aria-hidden="false" class="el-checkbox__original" value="">

这是组件变异太深了吗? 没有探究。

但我知道正常的 input 大概是这样:

<input type="checkbox" :checked="checked" :name="name" @change="change" :value="checked"/>

所以依照上面的规则,我自己写了一个 myCheckbox 组件:

<template>
   <input type="checkbox" 
    :name="name" 
   	:checked="checked" 
   	:value="checked"
   	@change="change" />
</template>

<script>
export default {
  props: {
    checked: {
      type: Boolean
    },
    name: {
      type: String
    }
  },
  model: {
    prop: 'checked',
    event: 'change'
  },
  methods: {
    change(e) {
      this.$emit('change', e.target.checked)
    }
  }
}
</script>

在父组件里使用:

<component :is="'myCheckbox'" v-model="checked" :name="'checked'"></component>

再次查看formData.getKey('checked') // true

功成名就。

推荐阅读