Home  >  Article  >  Web Front-end  >  How to encapsulate input components and unified form data in vue3

How to encapsulate input components and unified form data in vue3

WBOY
WBOYforward
2023-05-12 15:58:261826browse

Preparation

Use vue create example to create the project. The parameters are roughly as follows:

How to encapsulate input components and unified form data in vue3

Use native input

Native input is mainly value and change. Data needs to be synchronized when changing.

App.tsx is as follows:

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

Encapsulating Input

The benefits of encapsulating input are that it can pass values ​​directly, reduce logic, and no additional e.target# is needed. ##, prepare for subsequent encapsulation.

// Input.tsx
import { defineComponent, ref } from &#39;vue&#39;;

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

Use Input component

import { ref } from &#39;vue&#39;;
import Input from &#39;./components/Input&#39;;
export default {
  setup() {
    // 数据
    const username: any = ref(&#39;张三&#39;);
    return () => (
      <div>
        {/* 使用组件,传value和onChange */}
        <Input
          value={username.value}
          onChange={(value: string) => (username.value = value)} // 直接在这同步数据
        />
        <div>input的值:{username.value}</div>
      </div>
    );
  },
};

Encapsulate form data

Form data often needs to assign and obtain values. Here you can use classes to handle them uniformly, and assign attributes to subsequent components. extremely convenient.

The essence of useForm is proxy, which returns field data when accessing attributes, which can be used simply in form components.

/* 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(&#39;username&#39;,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 };
}

Using form data

The Input component works well with the form.

import Input from &#39;./components/Input&#39;;
import { useForm } from &#39;./hooks/useForm&#39;;

// 使用组件
export default {
  setup() {
    // 数据
    const { form, ver } = useForm({ username: &#39;张三&#39;, 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>
    );
  },
};

How to encapsulate input components and unified form data in vue3

The above is the detailed content of How to encapsulate input components and unified form data in vue3. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:yisu.com. If there is any infringement, please contact admin@php.cn delete