首页 > 其他分享 >小白的一次Form组件封装分享

小白的一次Form组件封装分享

时间:2023-05-12 18:32:34浏览次数:33  
标签:封装 Form 表单 props 组件 const model modelValue

Form组件介绍

form表单常用在回显表单信息 + 验证表单 + 提交表单信息。通常包含输入框, 选择框,日期选择框,文本框等可输入的组件。

封装思路

通过配置文件生成一个基本的表单,然后配合数据的双向绑定得到我们提交的数据,同时尽量保留第三方 UI 库组件提供的属性(Attributes)、插槽(Slots)和自定义事件(Events)

实现

1. 数据驱动

<template>
  <a-form
    :model="formState"
    name="basic"
    :label-col="{ span: 8 }"
    :wrapper-col="{ span: 16 }"
    autocomplete="off"
  >
    <a-form-item
      label="Username"
      name="username"
      :rules="[{ required: true, message: 'Please input your username!' }]"
    >
      <a-input v-model:value="formState.username" />
    </a-form-item>
    <a-form-item
      label="Password"
      name="password"
      :rules="[{ required: true, message: 'Please input your password!' }]"
    >
      <a-input-password v-model:value="formState.password" />
    </a-form-item>
    <a-form-item name="remember" :wrapper-col="{ offset: 8, span: 16 }">
      <a-checkbox v-model:checked="formState.remember">Remember me</a-checkbox>
    </a-form-item>
    <a-form-item :wrapper-col="{ offset: 8, span: 16 }">
      <a-button type="primary" html-type="submit">Submit</a-button>
    </a-form-item>
  </a-form>
</template>
  1. Form表单数据绑定在a-form上::model="form",form就是表单的数据对象。
  2. 表单里面的每一项是放在a-form-item标签里面,放入我们想渲染出来的组件,如输入框,选择框等。
  3. 每个a-form-item中可以绑定了label、rules等属性

通过分析Form代码我们可以通过一个配置文件去遍历a-form-item,然后在a-form-item上面绑定我们需要的属性,以及a-form-item标签里面各种输入组件。

这个配置文件应包括 label 标签的文本 name表单域 model 字段rules检验规则等表单的api,也应该包括内部可输入组件的api,比如类型(输入框、选择框、日期框等)

2.v-model实现父子组件双向数据绑定

原理: v-model绑定在组件上的时候做了以下步骤 在父组件内给子组件标签添加 v-model ,其实就是给子组件绑定了 value 属性 子组件内使用 props 拿到父组件传递下来的value。 子组件内部更改 value 的时候,必须通过 emit('update:value', e)更新父组件v-model绑定的变量

props 传值是单向的,即父组件中的数据改变会反映到子组件中,但在子组件内部不能主动改变 props的值,子组件中不能使用 v-model="modelValue" 之类方法试图直接改变父组件的值。

父组件 v-model传递的值的默认名称是modelValue,子组件通过props接收modelValue

<Ainput v-model="data" />

子组件

1.拆成:value='modelValue',监控子组件的更新事件触发emit('update:modelValue', e)

// 子组件
// 
<template>
  <div>
    <a-input :value="modelValue" v-bind="$attrs" @change="change" />
  </div>
</template>

<script lang="ts" setup name="AInput">
defineProps({
  modelValue: {
    type: String,
    default: '',
  },
})

const emit = defineEmits(['update:modelValue'])

// 更新modelValue
const change = (e: { target: HTMLInputElement }) => {
  emit('update:modelValue', e.target.value.trim())
}
</script>
  1. 通过计算属性computed的set/get实现双向绑定
// 子组件
<template>
  <div>
    <a-input v-model:value="modelValue" v-bind="$attrs" />
  </div>
</template>
<script lang="ts" setup name="AInput">
import { computed } from 'vue'

const props = defineProps({
  modelValue: {
    type: String,
    default: '',
  },
})

const emit = defineEmits(['update:modelValue'])

// 双向绑定
const formValue = computed({
   //get父组件的modelValue
  get: () => {
    return props.modelValue
  },
  // input更新formValue时触发set,set通过emit通知父组件更新modelValue
  set: (val) => {
    emit('update:modelValue', val)
    emit('getvalue', val, props.meta.colName)
  },
})
</script>

如果是对象的话可以使用vueuse的useVModel方法

<script lang="ts" setup>
import { useVModel } from '@vueuse/core'

const props = defineProps({
  //表单数据
  formData: {
    type: Object as PropType<ObjectExtends>,
    default: () => {
      return {}
    },
  },
})
const emit = defineEmits(['update:formData'])

// 实现双向绑定 每当 prop 发生变化时,model 就会改变。但只要它从这个组件中被改变,它就会发出update:formData, 通过父组件的v-model指令触发更新。
const model = useVModel(props, 'formData', emit)

</script>

3. Attributes透传

在 Vue 3.x 当中,通过v-bind$attrs属性就可以进行 props 属性和 event 事件的透传分发了。

$attrs透传属性包括props,events, class,style,id等。(不包含接收组件显式声明的 propsemits以及slots )

{
    title: 'input1',
    colName: 'input1',
    controlType: 100,
    rules: [{ required: true, message: 'input1不可为空' }],
    style: 'background: red',
    class: 'normalInput',
  },
// 子组件
<template>
  <div>
    <a-input v-model:value="modelValue" v-bind="$attrs" />
  </div>
</template>

如果不希望透传某些属性比如rules, 可以通过useAttrs来实现

// 子组件
<template>
  <div>
    <a-input v-model:value="modelValue" v-bind="filteredAttrs" />
  </div>
</template>
const attrs = useAttrs()
const filteredAttrs = computed(() => {
  return { ...attrs, rules: undefined }
})



标签:封装,Form,表单,props,组件,const,model,modelValue
From: https://blog.51cto.com/u_15719093/6271670

相关文章

  • 云原生第三周--kubernetes组件详解
    etcd组件etcd简介:etcd是CoreOS团队于2013年6月发起的开源项目,它的目标是构建一个高可用的分布式键值(key-value)数据库。etcd内部采用raft协议作为一致性算法,etcd基于Go语言实现。etcd具有下面这些属性:完全复制:集群中的每个节点都可以使用完整的存档高可用性:Etcd可用于避免......
  • 记录--9个封装Vue组件的小技巧
    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助组件是前端框架的基本构建块。把它们设计得更好会使我们的应用程序更容易改变和理解。在这节课中,分享一下在过去几年中工作中学到的9个技巧。1.你可能不需要创建一个组件在创建一个组件之前,看看它是为了可重用......
  • axios封装
    当我们调取后端接口时,请求会有多种结果,诸如401(未登录)、403(登录过期)、404(请求地址错误)、500(服务器繁忙)等,以往我们只会打开控制台查看原因,我们可以对此进行优化,当请求接口失败时,可以给出弹窗提示知道失败原因。项目中用到了elementui、qs,使用前需要下载service文件代码s......
  • 西门子1500PLC程序 宁德C公司 32组件涂胶PLC程序,硬件配置:1511
    西门子1500PLC程序宁德C公司32组件涂胶PLC程序,硬件配置:1511PLC,三个库卡机器人,一个个PN-COUPLER上下游通讯,滚筒电机,气缸,MES交互,康耐视相机扫码,四轴雅马哈机器人上料,台达伺服,涂胶机,程序完整西门子系列实际项目程序+触摸屏程序+新能源锂电设备故障记录功能,工位CT时间,历史报警,产量统......
  • c# 封装sealed修饰符
    使用sealed修饰的类,标识封装类,不能被继承,如classb不能被其他类继承;classA{}sealedclassB:A{}也能用sealed修饰重写的虚方法或属性,如下所示,Y类重写了X类的虚方法,并用sealed修饰F方法,那么,Z类就无法重写F方法,所以可以阻止后代重写sealed修饰的方法和属性;classX{prot......
  • 西门子1200脉冲运动控制程序 封装好的脉冲运动控制块,直接调用就好了,能实现手动,回原点,
    西门子1200脉冲运动控制程序封装好的脉冲运动控制块,直接调用就好了,能实现手动,回原点,走绝对位置,轴的设定值,轴的实际值,轴的状态,用起来绝对方便省心,博途西门子v15以上都可以打开,ID:5510669731623904......
  • google-java-format 插件
    GoogleJavaStyleGuidegoogle-java-formatgoogle-java-format插件可用于重新格式化Java源代码,。启用后,它将替换通常的ReformatCode操作。该操作可以通过Code->ReformatCode触发,也可以使用Ctrl+Alt+L触发。IDEA中使用google-java-format插件在File->Settings->Pl......
  • vue3 父子组件传值
    父传子组件<template><div><!--通过自定义属性传递值--><Subassembly:value="doc"/></div></template><scriptsetup>import{ref}from'vue'importSubassemblyfrom'./Subassembly.vue&#......
  • spring出现依赖关系形成循环问题,The dependencies of some of the beans in the appli
    出现这个问题大多使用的springboot都是在2.6.x以上,springboot在2.6.x就将依赖循环禁用了,解决方式有以下几种:解决方式:1、第一种解决方式:可以优化自己程序的逻辑,优化bean的依赖关系,只要不形成一个环状就不会出该问题了 2、第二种解决方式:可以使用@Lazy注解(懒加载)和@Autowired注......
  • axios 发送 form-data 请求和 x-www-form-urlencoded请求以及相关问题
    问题notsupported{"msg":"Contenttype'multipart/form-data;boundary=--------------------------714795402464721152224475;charset=UTF-8'notsupported","code":500}这个是因为form-data请求没有被后端支持,联系后端确认请求格式;关......