网络编程
位置:首页>> 网络编程>> JavaScript>> vue3简单封装input组件和统一表单数据详解

vue3简单封装input组件和统一表单数据详解

作者:颜酱  发布时间:2024-04-26 17:41:18 

标签:vue3,封装,input

前言

vue3 支持用 jsx 实现组件,摆脱了 vue 文件式的组件,不再需要额外的指令,写法非常接近 React,减少记忆负担。

本文简单的练习,用 vue3 组件封装 input 组件和统一表单数据。

准备工作

vue create example创建项目,参数大概如下:

vue3简单封装input组件和统一表单数据详解

用原生 input

原生的 input,主要是 value 和 change,数据在 change 的时候需要同步。

App.tsx如下:

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

封装 input 的好处,直接传值,减少逻辑,不再需要额外的e.target,为后面的继续封装做准备。

// Input.tsx
import { defineComponent, ref } from 'vue';

// defineComponent定义组件,有props
const 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} />;
 },
});

使用Input组件

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>
   );
 },
};

封装表单数据

表单数据,经常需要赋值、获取值,这边可以用类统一处理,在后面的组件赋值属性的时候极其方便。

useForm的精华,在于proxy,访问属性的时候,返回field数据,这在表单组件里可以简洁使用。

/* 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 };
}

使用表单数据

Input组件配合表单,使用效果奇佳。

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>
   );
 },
};

vue3简单封装input组件和统一表单数据详解

来源:https://juejin.cn/post/7100863271062175751

0
投稿

猜你喜欢

手机版 网络编程 asp之家 www.aspxhome.com