vue3简单封装input组件和统一表单数据详解
作者:颜酱 发布时间:2024-04-26 17:41:18
标签:vue3,封装,input
前言
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>
{/* 使用组件,传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>
);
},
};
来源:https://juejin.cn/post/7100863271062175751
0
投稿
猜你喜欢
- 前言Pandas是python的一个数据分析包,是基于NumPy的一种工具提供了大量数据结构和函数,可以很方便的处理结构化数据,常见数据结构
- 一、创建测试项目1、新建GitHub仓库在GitHub上面新创建一个仓库,用来演示分支管理,如下图所示:点击“Creat
- 普通方法:爬取梨视频import reimport timeimport randomimport requestsfrom lxml im
- 最近在学习python过程中,对print()打印输出函数进行了进一步学习。python 2.6中,print输出内容需要使用引号。pyth
- 今天偶然看到“一个有将近两年的div + CSS 开发经验和历史,曾经是Web标准绝对拥趸的同志”在自己的blog上发表放弃div+css的
- 1.el-input无法输入的问题原因1、el-input组件没有绑定双向响应式数据(v-model)解决方案:在data中定义一个变量,然
- YAML语法规则:http://www.ibm.com/developerworks/cn/xml/x-cn-yamlintro/下载PyY
- 本文实例为大家分享了python实现简易聊天室的具体代码,供大家参考,具体内容如下群聊聊天室1.功能:类似qq群聊功能1.有人进入聊天室需要
- 前言如果采用前后端分离的架构开发, 后端几乎不负责任何展现界面的工作,只负责对数据进行管理 。 数据的管理,主要就是:响应前端的请求, 对数
- 最近跟着OpenCV2-Python-Tutorials在学习python_opencv中直方图的反向投影时,第一种方法是使用numpy实现
- PDO::execPDO::exec — 执行一条 SQL 语句,并返回受影响的行数(PHP 5 >= 5.1.0, PECL pdo
- 详解Python文本操作相关模块linecache——通过使用缓存在内部尝试优化以达到高效从任何文件中读出任何行。 主要方法: lineca
- 以前我浏览博客的时候记得别人说过,BCELoss与CrossEntropyLoss都是用于分类问题。可以知道,BCELoss是Binary
- 楔子由于之前电脑上安装的MySQL版本是比较老的了,大概是5.1的版本,不支持JSON字段功能。而最新开发部门开发的的编辑器产品,使用到了J
- 1. 时间差函数(TIMESTAMPDIFF、DATEDIFF)需要用MySQL计算时间差,使用TIMESTAMPDIFF、DATEDIFF
- scipy.optimize函数使用简单使用scipy.optimize,训练逻辑回归损失函数,得到权值。scipy.optimize模块包
- 1. 项目背景视频传输: 在一台电脑上播放视频(捕捉摄像头画面),同局域网内另一台电脑上实时播放,尽量不卡顿。先放最后的照片,和用gif展示
- 一 介绍Python上有一个非常著名的HTTP库——requests,相信大家都听说过,用过的人都说非常爽!现在requests库的作者又发
- 通常,会话管理是通过服务器将 Session ID 作为一个 cookie 存储在用户的 Web 浏览器中来唯一标识每个用户会话。如果浏览器
- 用python的matplotlib画图时,往往需要加图例说明。如果不设置任何参数,默认是加到图像的内侧的最佳位置。import matpl