form 表单监听输入框值变化 - js、ts

本文分享了在Angular中如何使用valueChanges实时监听表单控件的变化,通过具体实例展示了如何对输入框的值变化进行订阅,从而实现联动操作和业务逻辑处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

日常开发中经常会用到 form 控件做一些操作,其中会涉及到一些动态监听某些控件数值参数发生改变而产生的相关联动操作,可以通过 valueChanges 的方式获取某些控件并进行订阅监听的操作,例如下面例子中所示:
对 form 表单中的 input 控件进行实时监听的操作;
首先,将控件创建完毕并对齐设置 formControlName 的 key 值;

<form (ngSubmit)="submitFormCellPhone()" [formGroup]="validateFormQuick" class="login-form" nz-form>
  <nz-form-item>
    <nz-form-control nzErrorTip="请输入手机号">
      <nz-input-group [nzPrefix]="prefixUser">
        <input formControlName="cellPhone" nz-input placeholder="手机号" type="text">
      </nz-input-group>
    </nz-form-control>
  </nz-form-item>
</form>

其次,在 js、ts 中通过 valueChanges 的方式绑定(get) 对应的控件的 key 属性,例如如下 code 中的 get('cellPhone').valueChanges 所示;

ngOnInit(): void {
    this.validateFormQuick = this.fb.group({ // 获取短信登录表单数据
      cellPhone: [null, [Validators.required]],
      messageCode: [null, [Validators.required]]
    });
    this.validateFormQuick.get('cellPhone').valueChanges.subscribe( data => { // 监听获取验证码按钮是否可点击
      // 处理相关业务逻辑。。。
      console.log(data);
      if (data) {
        this.msgDisabledState = false;
      } else {
        this.msgDisabledState = true;
      }
    });
  }

最后,对其设置订阅监听(subscribe)的操作,随后处理相关业务即可。

初识前端 angular 也在一步步的匍匐爬行中,有什么不佳之处还请大神多多指点!


以上便是此次分享的全部内容,希望能对大家有所帮助!

<think>我们将在Vue 3中创建一个可复用的表单组件,该组件可以动态地渲染包含el-input和el-select的表单项。我们将使用`<component :is="...">`来动态渲染不同的元素,同时使用v-bind绑定属性并处理事件。 步骤: 1. 定义组件的props,用于接收表单的配置项(配置项包括每个表单项的类型、绑定属性、选项(对于select)、占位符、校验规则等)。 2. 在组件内部,使用el-form包裹,并使用v-for循环渲染配置项。 3. 对于每个表单项,使用动态组件`:is`来决定是渲染el-input还是el-select。注意:在Vue3中,使用动态组件时,如果是全局注册的组件,可以直接使用组件名称的字符串(但注意Element Plus的组件名);或者我们也可以导入组件然后使用变量。 4. 绑定每个表单项的属性和事件。特别是要绑定v-model,但由于我们的数据是放在父组件中,所以我们可以使用`modelValue`作为prop,并在子组件中更新时触发`update:modelValue`事件。但更常见的是,我们希望表单数据对象作为一个整体prop传入,然后每个表单项绑定到这个对象的相应属性。 设计: - 我们将接收一个`formModel` prop,它是一个对象,表示表单的数据(例如:{ name: '', category: '' })。 - 接收一个`formItems` prop,它是一个数组,每个元素是一个配置对象,包括: - type: 'input' | 'select' 等(对应el-input或el-select) - prop: 字符串,对应formModel中的字段名 - label: 表单项的标签 - placeholder: 输入框的占位符 - options: 如果是select,则传递选项数组,每个选项为{ label: string, value: any } - ...其他可能需要传递给el-form-item或具体组件的属性(如校验规则等) 注意:由于我们可能还需要处理表单校验,所以我们可以通过ref暴露el-form的方法(如validate)。 实现: 1. 创建组件`ReusableForm.vue` 2. 在模板中使用el-form,并循环`formItems`生成el-form-item 3. 每个el-form-item内部使用动态组件,根据type渲染不同的输入组件 4. 对于el-select,需要循环options生成el-option 代码示例: ```vue <template> <el-form ref="formRef" :model="formModel" label-width="120px"> <el-form-item v-for="item in formItems" :key="item.prop" :label="item.label" :prop="item.prop" :rules="item.rules" > <!-- 动态组件 --> <component :is="getComponentType(item.type)" v-bind="item.attrs" v-model="formModel[item.prop]" :placeholder="item.placeholder" > <!-- 如果是select,需要循环options生成option --> <template v-if="item.type === 'select'"> <el-option v-for="opt in item.options" :key="opt.value" :label="opt.label" :value="opt.value" /> </template> </component> </el-form-item> </el-form> </template> <script setup> import { ref, defineProps, defineExpose } from 'vue' import { ElInput, ElSelect, ElOption } from 'element-plus' const props = defineProps({ formModel: { type: Object, required: true }, formItems: { type: Array, required: true, default: () => [] } }) // 获取组件类型,返回组件对象 const getComponentType = (type) => { switch (type) { case 'input': return ElInput case 'select': return ElSelect // 可以扩展其他类型 default: return ElInput } } // 暴露el-form的方法,以便父组件调用 const formRef = ref(null) defineExpose({ validate: () => formRef.value?.validate(), resetFields: () => formRef.value?.resetFields() }) </script> ``` 使用示例(在父组件中): ```vue <template> <ReusableForm :formModel="formData" :formItems="formItemsConfig" /> </template> <script setup> import { ref } from 'vue' import ReusableForm from './ReusableForm.vue' const formData = ref({ name: '', category: '' }) const formItemsConfig = ref([ { type: 'input', prop: 'name', label: '名称', placeholder: '请输入名称' }, { type: 'select', prop: 'category', label: '分类', placeholder: '请选择分类', options: [ { label: '分类1', value: '1' }, {label: '分类2', value: '2'} ] } ]) </script> ``` 注意事项: 1. 动态组件绑定v-model时,对于el-input和el-select,v-model的行为是一致的,都是绑定当前。 2. 如果需要处理其他事件(如change、blur等),可以在配置项中添加事件处理函数,并在动态组件上绑定相应事件。但注意,这里我们只处理了基本的绑定,更复杂的事件处理可能需要扩展配置项。 3. 我们通过`formItems`中的`attrs`属性(未在示例中展示)可以传递其他属性到组件上,例如:在配置项中添加`attrs: { clearable: true }`,然后通过`v-bind="item.attrs"`绑定。 4. 关于表单校验:我们在el-form-item上绑定了rules,这些规则可以放在每个表单项的配置中(如`item.rules`)。同时,我们通过暴露formRef,使得父组件可以调用表单的校验方法。 这样封装后,我们可以通过配置的方式生成不同的表单,提高了复用性。 §§相关问题§§ 1. 如何在动态表单组件中处理自定义事件(如change、blur)? 2. 如何扩展此表单组件以支持更多类型的表单元素(如el-checkbox, el-radio)? 3. 在Vue3中,如何更好地处理表单校验(使用async-validator)? 4. 如何实现表单的重置功能(resetFields)以及可能遇到的问题?[^3]</think>在 Vue 3 中创建可复用的 el-form 组件包含 el-select 和 el-input 元素,可以通过以下步骤实现: ### 解决方案 #### 1. 创建通用表单组件 ```vue <!-- ReusableForm.vue --> <template> <el-form ref="formRef" :model="formModel" :rules="rules" label-width="120px"> <el-form-item v-for="field in formFields" :key="field.prop" :label="field.label" :prop="field.prop" > <!-- 动态渲染输入组件 --> <component :is="getComponentType(field.type)" v-model="formModel[field.prop]" v-bind="field.attrs" :placeholder="field.placeholder" > <!-- 下拉框选项 --> <el-option v-if="field.type === 'select'" v-for="opt in field.options" :key="opt.value" :label="opt.label" :value="opt.value" /> </component> </el-form-item> </el-form> </template> <script setup lang="ts"> import { ref, computed } from 'vue' import { ElInput, ElSelect } from 'element-plus' // 定义组件接受的属性 const props = defineProps({ formFields: { type: Array as () => FormField[], required: true }, initialData: { type: Object, default: () => ({}) }, rules: { type: Object, default: () => ({}) } }) // 表单字段类型定义 interface FormField { type: 'input' | 'select' // 组件类型 prop: string // 数据字段名 label: string // 表单项标签 placeholder?: string // 占位文本 options?: { // 下拉框选项 label: string value: string | number }[] attrs?: Record<string, any> // 额外属性 } // 表单数据模型 const formModel = ref({ ...props.initialData }) // 动态获取组件类型 const getComponentType = (type: string) => { return type === 'select' ? ElSelect : ElInput } // 暴露表单方法给父组件 defineExpose({ validate: () => formRef.value?.validate(), resetFields: () => { formRef.value?.resetFields() formModel.value = { ...props.initialData } }, getFormData: () => ({ ...formModel.value }) }) const formRef = ref() </script> ``` #### 2. 在父组件中使用 ```vue <!-- ParentComponent.vue --> <template> <ReusableForm ref="reusableForm" :formFields="fields" :initialData="formData" :rules="formRules" /> <el-button @click="submitForm">提交</el-button> <el-button @click="resetForm">重置</el-button> </template> <script setup lang="ts"> import { ref } from 'vue' import ReusableForm from './ReusableForm.vue' // 表单配置数据 const fields = ref([ { type: 'input', prop: 'username', label: '用户名', placeholder: '请输入用户名', attrs: { clearable: true } }, { type: 'select', prop: 'role', label: '用户角色', placeholder: '请选择角色', options: [ { label: '管理员', value: 1 }, { label: '编辑', value: 2 }, { label: '访客', value: 3 } ] } ]) // 初始表单数据 const formData = ref({ username: '', role: '' }) // 表单验证规则 const formRules = ref({ username: [ { required: true, message: '用户名不能为空', trigger: 'blur' } ], role: [ { required: true, message: '请选择用户角色', trigger: 'change' } ] }) const reusableForm = ref() // 提交表单 const submitForm = async () => { try { await reusableForm.value.validate() const formData = reusableForm.value.getFormData() console.log('提交数据:', formData) // 提交到API... } catch (error) { console.error('表单验证失败:', error) } } // 重置表单 const resetForm = () => { reusableForm.value.resetFields() } </script> ``` ### 关键实现说明 1. **动态组件渲染**: - 使用 Vue 的 `component` 组件和 `:is` 指令动态渲染 `ElInput` 或 `ElSelect` - 通过 `getComponentType` 方法映射类型到组件对象[^1] 2. **通用配置接口**: - `formFields` 属性定义表单结构,支持扩展字段类型 - 每个字段包含 `type`、`prop`、`label` 等配置项 3. **表单状态管理**: - 使用 `formModel` 响应式对象管理表单数据 - 通过 `initialData` 属性初始化表单 4. **表单方法暴露**: - 使用 `defineExpose` 暴露 `validate`、`resetFields` 等方法 - 父组件可通过 ref 调用这些方法[^3] 5. **验证规则支持**: - 接受 `rules` 属性传递验证规则 - 集成 Element Plus 的原生验证机制 ### 注意事项 1. **重置功能优化**: - 自定义 `resetFields` 方法同时重置表单状态和初始数据 - 避免直接使用 Element 的 resetFields 在复用场景下的问题[^3] 2. **类型扩展**: 要添加新组件类型(如 checkbox),只需: ```typescript const getComponentType = (type: string) => { switch(type) { case 'select': return ElSelect case 'checkbox': return ElCheckbox default: return ElInput } } ``` 3. **复杂场景处理**: - 对于联动字段,可在父组件监听变化并更新 `formFields` - 使用 `watch` 监听 `initialData` 变化更新表单
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值