vue3怎么封装input组件和统一表单数据
时间:2023-05-13 01:04
用 原生的 input,主要是 value 和 change,数据在 change 的时候需要同步。 App.tsx如下: 封装 input 的好处,直接传值,减少逻辑,不再需要额外的 使用Input组件 表单数据,经常需要赋值、获取值,这边可以用类统一处理,在后面的组件赋值属性的时候极其方便。 useForm的精华,在于proxy,访问属性的时候,返回field数据,这在表单组件里可以简洁使用。 Input组件配合表单,使用效果奇佳。 以上就是vue3怎么封装input组件和统一表单数据的详细内容,更多请关注Gxl网其它相关文章!准备工作
vue create example
创建项目,参数大概如下:用原生 input
import { ref } from 'vue';export default { setup() { // username就是数据 const username = ref('张三'); // 输入框变化的时候,同步数据 const onInput = ; return () => ( <div> <input type="text" value={username.value} onInput={(e: any) => { username.value = e.target.value; }} /> <div>input的值:{username.value}</div> </div> ); },};
封装 Input
e.target
,为后面的继续封装做准备。// Input.tsximport { defineComponent, ref } from 'vue';// defineComponent定义组件,有propsconst Input = defineComponent({ props: { value: { required: true, type: String, }, onChange: { required: true, type: Function, }, }, // 渲染用到props,需要在这里传参 setup(props) { // 值变化 的时候 调用传过来的onChange从而同步父组件的 数据 const onInput = (e: any) => { props.onChange && props.onChange(e.target.value); }; return () => <input type="text" value={props.value} onInput={onInput} />; },});
import { ref } from 'vue';import Input from './components/Input';export default { setup() { // 数据 const username: any = ref('张三'); return () => ( <div> {/* 使用组件,传value和onChange */} <Input value={username.value} onChange={(value: string) => (username.value = value)} // 直接在这同步数据 /> <div>input的值:{username.value}</div> </div> ); },};
封装表单数据
/* eslint-disable @typescript-eslint/explicit-module-boundary-types *//* eslint-disable @typescript-eslint/no-explicit-any */import { ref, Ref } from "vue";export class FormData<T> { private data: Ref<any>; constructor(data: T) { this.data = ref(data || null); } // 设置某个字段的值 setValue(name: string, val: any): void { const next = { ...this.data.value, [name]: val }; this.data.value = next; } // 获取某个字段的值 getValue(name: string): any { return this.data.value[name]; } // 获取整个值 getValues() { return this.data.value; } // 设置整个值 setValues(values: T) { this.data.value = values; } // 获取field,字段和字段的修改事件 getField(name: string) { return { value: this.data.value[name], onChange: (v: any) => { this.setValue(name, v); }, }; }}type FormDataProxy<T> = { [P in keyof T]: T[P];};export function useForm<T extends Record<string, any>>(data: T) { const form = new FormData(data); const ver = ref(0); const proxy = new Proxy(form, { // 写proxy的目的是:form.username的时候,直接返回 form.getField(username) get(target, name) { switch (name) { case "getValues": return form.getValues.bind(form); case "setValues": return form.setValues.bind(form); default: return form.getField(name as string); } }, // 写form.username = xx 直接返回 form.setValue('username',xx) set(target, name, value) { switch (name) { case "getValues": case "setValues": break; default: form.setValue(name as string, value); } return true; }, }) as any as FormDataProxy<T> & { setValues: (val: T) => void; getValues: () => Ref<T>; }; return { form: proxy, ver };}
使用表单数据
import Input from './components/Input';import { useForm } from './hooks/useForm';// 使用组件export default { setup() { // 数据 const { form, ver } = useForm({ username: '张三', age: 33 }); console.log(123, form, ver); return () => ( <div> {/* 这里的form.username,实际是proxy返回的{value:xxx,onChange:fn} */} {/* 多表单组件的时候 这样就非常方便了 */} <Input {...form.username} /> <Input {...form.age} /> <button onClick={() => { console.log(form.getValues()); }} > 提交 </button> </div> ); },};