浅析五种 React 组件设计模式( 二 )

  • 一致性和可预测性: React 组件的状态是单一数据源,使得应用的状态变得更加可预测和一致 。状态的变化完全由 React 控制,减少了意外的行为 。 缺点:
  • 繁琐的代码: 受控组件相对于非受控组件来说,需要更多的代码 。每个输入框都需要设置对应的状态和事件处理函数,这可能导致代码量的增加 。
  • 性能开销: 受控组件每次输入变化都会触发状态更新,可能导致频繁的重新渲染 。对于大型或性能敏感的应用,这可能带来一些性能开销 。
  • 不适用于所有场景:受控组件更适用于表单交互比较复杂,需要实时验证或涉及多个输入字段之间关系的场景 。对于简单的表单,可能显得有些繁重 。
  • 适用场景:
    • 动态表单元素: 在需要动态添加或删除表单元素的情况下 , 受控组件模式可以很容易地实现 。通过使用数组来保存表单元素的状态,可以动态渲染和更新表单 。
    • 模态框控制: 当需要通过 props 控制模态框的显示或隐藏状态时,可以使用受控组件模式 。
    3. 自定义 Hooks 模式自定义Hooks模式是一种将组件逻辑提取为可重用的函数的方法 。将主要的逻辑转移到一个Hooks中 。用户可以访问这个Hooks,并公开了几个内部逻辑(状态、处理程序),使用户能够更好地控制组件 。
    import React, { useState } from 'react';const Button = ({ label, onClick }) => (<button onClick={onClick}>{label}</button>);const TextBox = ({ value, onChange, placeholder }) => (<input type="text" value=https://www.isolves.com/it/cxkf/bk/2024-01-09/{value} onChange={onChange} placeholder={placeholder} />);// 自定义 Hook,处理登录表单逻辑const useLoginForm = () => {const [loginData, setLoginData] = useState({ username: '', password: '' });const handleInputChange = (e) => {const { name, value } = e.target;setLoginData((prevData) => ({...prevData,[name]: value,}));};const handleLogin = () => {// 在这里实现登录逻辑console.log(`使用用户名 ${loginData.username} 和密码 ${loginData.password} 登录`);};return {loginData,handleInputChange,handleLogin,};};// 在组件中使用自定义 Hookconst ControlledLoginPanel = () => {const { loginData, handleInputChange, handleLogin } = useLoginForm();return (
    );};// 使用示例const App = () => {return ();};export default App;
    在这个例子中,我们将与登录表单相关的状态和逻辑抽离到一个自定义 useLoginForm Hook 中 。使得 ControlledLoginPanel 组件更专注于渲染 UI , 减少了状态和事件处理逻辑的混杂 。
    优点:
    • 逻辑重用: 将逻辑提取为 Hooks,可以在多个组件中重用 。
    • 组件更简洁: 组件代码更加清晰,只关注与 UI 相关的逻辑 。 缺点:
    • 实现复杂度变高: 逻辑部分与渲染部分分开 , 需要将两者结合起来才能很好的理解组件工作原理 。 适用场景:
    • 数据获取和处理逻辑: 将数据获取和处理逻辑提取到自定义 Hook 中 , 可以在多个组件之间共享相同的数据逻辑 。
    • 副作用的封装: 当有需要在组件中处理副作用的情况,可以将副作用逻辑封装到自定义 Hook 中,以提高可维护性 。
    4. Props Getters 模式模式 3 中的自定义Hooks提供了很好的控制方式;但是比较难以集成 , 使用者需要按照组件提供的Hooks与State相结合进行编写逻辑 , 提高了集成的复杂度 。Props Getters模式则是通过简化这一过程来实现 。Getter是一个返回多个属性的函数,它具有有意义的名称,使得开发者能够清楚地知道哪个Getter对应于哪个JSX元素 。
    import React, { useState } from 'react';const Button = ({ getLabel, handleClick }) => (<button onClick={handleClick}>{getLabel()}</button>);const TextBox = ({ getValue, onChange, placeholder }) => (<input type="text" value=https://www.isolves.com/it/cxkf/bk/2024-01-09/{getValue()} onChange={onChange} placeholder={placeholder} />);const ControlledLoginPanel = ({ getUsernameProps, getPasswordProps, handleLogin }) => {return (


    推荐阅读