如何优雅的在 Material UI 中使用 form

您所在的位置:网站首页 mui下拉框select 如何优雅的在 Material UI 中使用 form

如何优雅的在 Material UI 中使用 form

2023-09-23 05:49| 来源: 网络整理| 查看: 265

你可能想问我为什么不直接用 antd ?

Material UI 可能在国内的公司和前端圈子里并不火热,因为他们有 antd,诚然 antd 确实是一套非常好的企业级解决方案,阿里也是这么为其定位的,但是其作为一个单纯的 UI 框架其实过于复杂了,过于封装了,会让使用者经常感觉到不自由,并且会让代码的重复度和 UI 的重复度过高,然而其实这个在企业级的后台管理系统中是好事,能够让风格和使用方法统一,降低学习成本。但是对于前端最重要的领域,也就是能够做出风格各异,功能差别很大的页面等场景,使用 antd 往往并非最好的选择,尤其是在 to C 产品中,你基本不可能看到 antd 的影子,而 MUI 在这方面做的却很好,只负责单元物料的风格统一,而如何组合,如何拓展和封装,则是完全交还给开发者,这也是 Material Design 的魅力所在,即使 Google 在他们的产品中大量使用该设计风格,你却很少会感觉到页面的单一和重复。

因此在 Material UI 中控制 form 和在其他任何一个框架,甚至是原生 React 应用中使用 form 没有任何区别,并且Material UI 中很多 React hook 的实现更是符合未来 React 官方推荐的代码风格。

实际上 antd 中的 rc-form 的实现就仍然是基于受控组件和 state 管理实现的,antd 实际上为其中的每一个实现都又重新起了一个自己的名字,大多数情况下这些名字可能会让你的代码看起来更加凌乱和难以理解,而必不可少的 Form.create() 实际上就是一个高阶组件,过多的使用高阶组件也可能会让代码的 DOM 层级无谓的增加,然而最为让人头痛的实际上是最常用的 form 表单值的获取。如果你想单独获取一个或多个值你需要写很多你自己不知道为什么要这样写的代码,比如为什么表单的 form 对象会出现在组件的 props 中,而如果一个父级组件想获取子组件中的表单就更复杂了,你一定要把子组件的 ref 绑定到父组件中才能对其验证和取值,而这些代码实际上是很冗余的,让使用者与原生 form 完全割裂,让使用者对 antd 产生过度的依赖,甚至离开 antd 就不会处理表单。

受控组件和非受控组件

可能对于很多长年使用 antd 的 rc-form 的人来说,这两个概念会变得非常模糊,然而实际上在大多数 React 应用中,这才是真正用来处理 form 的最常用的方法,两种方法各有利弊,可能相比于 antd 封装好的组件使用上都会更为复杂一点,但是解决方案更为通用和容易理解,因为多数情况下,我们并不推荐为了处理表单而引入整个 UI 框架,而且这种编程方式更贴近于原生,能让人知道自己在干什么,相比 re-form 代码的可读性也有了保障。

受控组件

对于 form 中的每一个字段 input radio 等,都为其绑定一个 state ,每次输入的值发生改变都通过 onValueChange 来重新进行 setState 同时将 input 的 Value 也直接绑定为 state 上对应的值。 这种方法的优点在于,利用 state 的特性,我们可以很容易的对其进行提取和格式化,同样每次输入的改变都会通知也意味着每一次值的改变我们都可以及时的对其进行验证。而这种方法存在的问题就是,我们需要为组件添加很多的 state ,如果该组件的表单项很多的话,组件的 state 会堆积很长一串,而这些数据中大多数都是只需要取最后值的,没有必要一定要将其设置为 state,同时由于每一次改变都会重新 setState 也就意味着每一次输入都伴随着一次重复渲染,而且我们往往在这个情况下也不会为其增加防抖,那么所带来的重复渲染的意义也是不大的。

非受控组件

更为贴近原生 form 的一种方法,与 React 的控制基本无关,只是通过 ref 来直接获取表单 DOM 从而获取 Value。这种方式更为直接,但其存在的弊端同样很多,如不能及时对其进行表单验证,对于每一个节点都要去手动绑定 ref 等。在大多数的情况下和多数的 form 库中的实现基本上都还是基于受控组件和 state 管理的基础之上的。

搭配 react-hook-form

这简直是我见过的最优雅的处理 form 的库了,全库只有不到十个 API ,并且实现完全基于 React hook (意味着你的 React 版本同样要支持 hook )可以说是融合了受控组件和非受控组件的优点,让组件的值获取不在依赖 DOM,也不需要依赖 state ,也就不会有那么多的 re-render 同样他的 validate 也很好用,因为其拓展了 H5 中的原生 validate 模块,在使用的过程中也会对原生编程有更深的理解,让我们来看一个简单的🌰

nQBhNvFCDom3c7K.png

lQXE9c5ThLpeBPg.png

Tj7ZvHVmufLlAJR.png

const SignInSide = props => { const classes = useStyles() const { register, handleSubmit, errors } = useForm() const handleLogin = data => { console.log(errors) console.log(data) props.dispatch(actions.asyncLogin(data)) } const handleAuth = () => { props.dispatch(actions.asyncAuth()) } return ( Sign in Sign In Forgot password? {"Don't have an account? Sign Up"} ) }

因为 Material UI 并没有提供给我们 validate 的接口,只是在 TextField 中给了我们一个验证出错的样式,而这里我们结合使用 rhf 的 error 机制可以为不同的验证定义不同的提示,同时可以做到很完美的一个验证动画的反馈,而提交的表单数据只有在通过所有验证之后才会传入到 handleLogin 中,可以直接自由使用,如果想要传到父组件中,那么就通过 props 把这个方法传过来就好啦。

如果觉得这样使用会比较麻烦的话可以自己基于原生的 Input 自己对其进行和 rhf 的整合封装,这同样也是 Material UI 鼓励大家去做的。

Reference

Controlled and uncontrolled form inputs in React don’t have to be complicated - Gosha Arinich

AntDesign表单的理解与使用 - 掘金

GitHub - react-hook-form/react-hook-form: 📋 React hooks for form validation without the hassle



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3