前言
vue3 支持用 jsx 实现组件,摆脱了 vue 文件式的组件,不再需要额外的指令,写法非常接近 React,减少记忆负担。
本文简单的练习,用 vue3 组件封装 input 组件和统一表单数据。
准备工作
用vue create example
创建项目,参数大概如下:
用原生 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>
{}
<Input
value={username.value}
onChange={(value: string) => (username.value = value)} // 直接在这同步数据
/>
<div>input的值:{username.value}</div>
</div>
);
},
};
封装表单数据
表单数据,经常需要赋值、获取值,这边可以用类统一处理,在后面的组件赋值属性的时候极其方便。
useForm的精华,在于proxy,访问属性的时候,返回field数据,这在表单组件里可以简洁使用。
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>
{}
{}
<Input {...form.username} />
<Input {...form.age} />
<button
onClick={() => {
console.log(form.getValues());
}}
>
提交
</button>
</div>
);
},
};
总结
到此这篇关于vue3简单封装input组件和统一表单数据的文章就介绍到这了,更多相关vue3封装input组件内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!