React基础学习-Day02

2024-07-13 1128阅读

React基础学习-Day02

1.受控表单绑定

在 React 中,受控表单(controlled form)是一种通过 React 组件状态(state)来管理表单元素值的方式。使用受控表单,可以将表单元素的值与 React 组件的状态保持同步,从而实现对表单数据的完全控制和管理。

React基础学习-Day02
(图片来源网络,侵删)

如何创建受控表单

1. 输入框(Input)

使用 元素作为例子,展示如何创建一个受控输入框:

import React, { useState } from 'react';
const ControlledFormExample = () => {
  // 定义一个状态变量来存储输入框的值
  const [inputValue, setInputValue] = useState('');
  // 处理输入框值变化的函数
  const handleInputChange = (event) => {
    setInputValue(event.target.value);  // 更新状态变量的值
  };
  // 提交表单时处理函数
  const handleSubmit = (event) => {
    event.preventDefault();  // 阻止表单默认提交行为
    alert(`Submitted value: ${inputValue}`);  // 弹出输入框的当前值
  };
  return (
    
      
        Input:
        
      
      Submit
    
  );
};
export default ControlledFormExample;
2. 复选框(Checkbox)

对于复选框,需要注意初始状态和处理函数的变化:

import React, { useState } from 'react';
const CheckboxExample = () => {
  // 定义一个状态变量来存储复选框的选中状态
  const [isChecked, setIsChecked] = useState(false);
  // 处理复选框状态变化的函数
  const handleCheckboxChange = (event) => {
    setIsChecked(event.target.checked);  // 更新状态变量的值
  };
  // 提交表单时处理函数
  const handleSubmit = (event) => {
    event.preventDefault();  // 阻止表单默认提交行为
    alert(`Checkbox checked: ${isChecked}`);  // 弹出复选框的当前选中状态
  };
  return (
    
      
        Checkbox:
        
      
      Submit
    
  );
};
export default CheckboxExample;
3. 下拉菜单(Select)

对于 元素,需要注意选项列表的处理和初始选中值:

import React, { useState } from 'react';
const SelectExample = () => {
  // 定义一个状态变量来存储选择框的当前选中值
  const [selectedValue, setSelectedValue] = useState('option1');
  // 处理选择框选项变化的函数
  const handleSelectChange = (event) => {
    setSelectedValue(event.target.value);  // 更新状态变量的值
  };
  // 提交表单时处理函数
  const handleSubmit = (event) => {
    event.preventDefault();  // 阻止表单默认提交行为
    alert(`Selected value: ${selectedValue}`);  // 弹出选择框的当前选中值
  };
  return (
    
      
        Select:
        
          Option 1
          Option 2
          Option 3
        
      
      Submit
    
  );
};
export default SelectExample;

特点和优势

  • 完全控制: 受控表单使得所有表单元素的值都由 React 组件状态管理,可以通过状态更新函数精确控制和验证输入。
  • 一致性和可预测性: 因为状态直接驱动表单元素的值,所以可以确保表单的行为一致和可预测。
  • 验证和处理: 可以轻松实现输入验证、条件渲染和复杂的表单逻辑,例如禁用按钮直到所有必填字段都填写完毕。

    通过使用受控表单,React 组件能够更加灵活和可控地处理用户输入,提高了应用的可维护性和用户体验。

    2.React中如何获取DOM

    在 React 中获取 DOM 元素通常是通过 Refs(引用)来实现的。Refs 提供了一种直接访问在 render 方法中创建的 DOM 节点或 React 元素的方式。这种访问方式是为了避免直接操作 DOM,符合 React 的声明式和组件化的设计理念。

    使用 Refs 获取 DOM

    1. 创建 Refs

    在函数式组件中,可以使用 useRef 钩子来创建 Ref 对象:

    import React, { useRef } from 'react';
    const MyComponent = () => {
      // 创建一个 Ref 对象
      const myRef = useRef(null);
      // 在 useEffect 中操作 Ref
      useEffect(() => {
        console.log(myRef.current);  // 输出 Ref 对象的当前值(关联的 DOM 节点)
      }, []);
      return (
        
          {/* 这里是组件内容 */}
        
      );
    };
    export default MyComponent;
    
    2. 访问 DOM 节点

    通过 ref.current 属性可以访问到 Ref 对象关联的 DOM 节点。需要注意的是,Ref 对象在组件的整个生命周期中保持不变,但 ref.current 的值会随着组件的渲染和卸载而变化。

    3. 类组件中的 Refs

    在类组件中,Refs 的创建和访问稍有不同:

    import React, { Component } from 'react';
    class MyComponent extends Component {
      constructor(props) {
        super(props);
        // 创建一个 Ref 对象
        this.myRef = React.createRef();
      }
      componentDidMount() {
        console.log(this.myRef.current);  // 输出 Ref 对象的当前值(关联的 DOM 节点)
      }
      render() {
        return (
          
            {/* 这里是组件内容 */}
          
        );
      }
    }
    export default MyComponent;
    

    在类组件中,通过 React.createRef() 方法创建 Ref 对象,并在 componentDidMount 生命周期中访问 this.myRef.current 获取 DOM 节点。

    使用场景

    • 直接操作 DOM: 当需要在 React 中进行 DOM 操作时,例如测量元素尺寸、动画操作等,可以使用 Refs 来获取并操作 DOM 元素。
    • 集成第三方库: 当需要与不支持 React 的第三方库(如 D3.js、Chart.js 等)集成时,Refs 提供了一种访问和控制 DOM 的方式。
    • 焦点控制: 控制输入框、模态框等组件的焦点状态。

      注意事项

      • 避免滥用 Refs: 在大多数情况下,应该优先考虑使用 React 的数据驱动和状态管理方式,而不是直接操作 DOM。
      • Refs 和函数式组件: 在函数式组件中,确保使用 useRef 钩子来创建 Ref 对象,而不是直接操作 DOM。

        通过使用 Refs,在 React 中可以安全地获取和操作 DOM 元素,同时保持 React 的组件化和声明式编程模型的优势。

        3.组件间通信

        在 React 中,组件间通信是非常常见和重要的一部分,特别是在大型应用程序中,不同组件之间需要相互传递数据、状态或触发特定行为。以下是几种主要的 React 组件间通信方式:

        1. Props 属性传递

        Props(属性)是 React 中组件间通信最基础和常见的方式。通过将数据或函数作为属性传递给子组件,可以实现父组件向子组件的数据传递。

        父组件传递数据给子组件:

        // ParentComponent.jsx
        import React from 'react';
        import ChildComponent from './ChildComponent';
        const ParentComponent = () => {
          const data = 'Hello from parent';
          return (
            
              
            
          );
        };
        export default ParentComponent;
        

        子组件接收并使用 Props 数据:

        // ChildComponent.jsx
        import React from 'react';
        const ChildComponent = (props) => {
          return (
            
              

        {props.message}

        ); }; export default ChildComponent;

        2. Callback 函数传递

        通过将回调函数作为 Props 传递给子组件,子组件可以调用该函数并将数据或事件传递回父组件。

        父组件定义回调函数并传递给子组件:

        // ParentComponent.jsx
        import React, { useState } from 'react';
        import ChildComponent from './ChildComponent';
        const ParentComponent = () => {
          const [message, setMessage] = useState('');
          const handleCallback = (data) => {
            setMessage(data);
          };
          return (
            
              

        Message from child: {message}

        ); }; export default ParentComponent;

        子组件调用回调函数并传递数据:

        // ChildComponent.jsx
        import React from 'react';
        const ChildComponent = (props) => {
          const sendDataToParent = () => {
            const data = 'Hello from child';
            props.callback(data);
          };
          return (
            
              Send Data
            
          );
        };
        export default ChildComponent;
        

        3. Context API

        Context API 提供了一种在组件树中传递数据的方法,避免了通过 Props 层层传递数据的繁琐过程。适合在多层级嵌套的组件中使用,允许跨越组件层级直接传递数据。

        创建 Context 对象并提供数据:

        // MyContext.js
        import React from 'react';
        const MyContext = React.createContext();
        export const MyProvider = MyContext.Provider;
        export const MyConsumer = MyContext.Consumer;
        

        使用 Context 提供数据并在子组件中消费:

        // ParentComponent.jsx
        import React from 'react';
        import { MyProvider } from './MyContext';
        import ChildComponent from './ChildComponent';
        const ParentComponent = () => {
          const data = 'Hello from context';
          return (
            
              
            
          );
        };
        export default ParentComponent;
        

        在子组件中消费 Context 中的数据:

        // ChildComponent.jsx
        import React, { useContext } from 'react';
        import { MyContext } from './MyContext';
        const ChildComponent = () => {
          const data = useContext(MyContext);
          return (
            
              

        {data}

        ); }; export default ChildComponent;

        4. Redux 或其他状态管理工具

        对于大型应用程序中复杂的状态管理需求,可以使用 Redux 或其他状态管理工具(如 MobX)来集中管理应用程序的状态,并通过全局状态来实现组件间通信。这种方式适合需要多个组件共享状态或频繁更新状态的场景。

        选择合适的通信方式

        • Props 传递:简单、直观,适用于父子组件间的数据传递。
        • Callback 函数:父组件可以向子组件传递函数来处理子组件中的事件,适合于子组件向父组件传递数据或事件。
        • Context API:适用于跨组件层级传递数据,避免 Props 层层传递的麻烦。
        • Redux 或其他状态管理工具:适用于需要全局状态管理或复杂的状态更新和同步需求的应用程序。

          根据具体的场景和需求,选择适合的组件间通信方式是提高 React 应用开发效率和可维护性的关键。

          4.useEffect

          useEffect 是 React Hooks 中非常重要的一个钩子函数,用于在函数组件中执行副作用操作。副作用操作通常包括订阅数据、手动操作 DOM 和执行数据获取等。

          基本用法

          import React, { useEffect, useState } from 'react';
          const MyComponent = () => {
            // 定义一个状态来存储数据
            const [data, setData] = useState(null);
            // useEffect 第一个参数是一个函数,第二个参数是一个数组
            useEffect(() => {
              // 在组件加载后和每次更新后执行
              // 这里可以进行数据获取、订阅操作、手动 DOM 更新等异步操作
              fetchData();
              // 清理函数,可选,用于清理副作用
              return () => {
                cleanupFunction();
              };
            }, []); // 空数组意味着只在组件加载后执行一次
            const fetchData = async () => {
              // 异步操作示例,获取数据
              const result = await fetch('https://api.example.com/data');
              const data = await result.json();
              setData(data);
            };
            const cleanupFunction = () => {
              // 清理函数,比如清除订阅或取消定时器
              // 在组件卸载时执行
            };
            return (
              
                {data ? (
                  

          Data loaded: {JSON.stringify(data)}

          ) : (

          Loading...

          )} ); }; export default MyComponent;

          useEffect 的工作原理

          • 第一个参数(effect):一个函数,包含需要执行的副作用操作,可以是数据获取、订阅操作、DOM 操作等异步任务。
          • 第二个参数(dependencies 数组):可选参数,指定 effect 的依赖项。当依赖项发生变化时,effect 就会重新执行。如果不传递该参数,每次组件更新时都会执行 effect。

            依赖项的作用

            • 空数组 []:effect 仅在组件加载和卸载时执行,相当于 componentDidMount 和 componentWillUnmount 生命周期的结合体。
            • 包含状态或属性的数组:effect 会在依赖项中的状态或属性发生变化时执行。比如 [count] 会在 count 状态更新时执行 effect。
            • 不传递第二个参数:effect 在每次组件更新时都会执行,相当于 componentDidUpdate 生命周期。

              清理副作用

              在 effect 函数中可以返回一个清理函数,用于清理副作用,比如取消订阅、清除定时器等。这样可以避免内存泄漏和无效的异步操作。

              useEffect(() => {
                const subscription = subscribeToData();
                
                return () => {
                  subscription.unsubscribe(); // 清理订阅
                };
              }, [dependency]);
              

              总结

              useEffect 是 React Hooks 提供的强大工具,用于处理函数组件中的副作用操作。通过指定依赖项数组,可以精确控制 effect 的执行时机,避免不必要的重复执行,提高组件性能和可维护性。

              5.自定义Hook

              自定义 Hook 是 React 中的一个强大功能,它允许你将组件逻辑提取到可复用的函数中。自定义 Hook 的命名通常以 use 开头。

              创建一个自定义 Hook

              我们将创建一个简单的自定义 Hook useCounter,它管理一个计数器的状态并提供增加和减少计数器的方法。

              Step 1: 定义自定义 Hook
              import { useState } from 'react';
              const useCounter = (initialValue = 0) => {
                const [count, setCount] = useState(initialValue);
                const increment = () => setCount(count + 1);
                const decrement = () => setCount(count - 1);
                return { count, increment, decrement };
              };
              export default useCounter;
              
              Step 2: 使用自定义 Hook

              你可以在任意函数组件中使用这个自定义 Hook:

              import React from 'react';
              import useCounter from './useCounter';
              const CounterComponent = () => {
                const { count, increment, decrement } = useCounter(10);
                return (
                  
                    

              Count: {count}

              Increment Decrement ); }; export default CounterComponent;

              自定义 Hook 的优势

              1. 逻辑复用:将重复使用的逻辑提取到自定义 Hook 中,使代码更加模块化和可复用。
              2. 更清晰的组件结构:通过将复杂逻辑抽离到自定义 Hook 中,组件代码变得更简洁和易读。
              3. 状态隔离:每次调用自定义 Hook 都会生成独立的状态,互不影响。

              复杂的自定义 Hook 示例

              创建一个自定义 Hook useFetch 来处理数据获取:

              Step 1: 定义 useFetch Hook
              import { useState, useEffect } from 'react';
              const useFetch = (url) => {
                const [data, setData] = useState(null);
                const [loading, setLoading] = useState(true);
                const [error, setError] = useState(null);
                useEffect(() => {
                  const fetchData = async () => {
                    try {
                      const response = await fetch(url);
                      if (!response.ok) {
                        throw new Error('Network response was not ok');
                      }
                      const data = await response.json();
                      setData(data);
                    } catch (error) {
                      setError(error);
                    } finally {
                      setLoading(false);
                    }
                  };
                  fetchData();
                }, [url]);
                return { data, loading, error };
              };
              export default useFetch;
              
              Step 2: 使用 useFetch Hook
              import React from 'react';
              import useFetch from './useFetch';
              const DataComponent = () => {
                const { data, loading, error } = useFetch('https://api.example.com/data');
                if (loading) return 

              Loading...

              ; if (error) return

              Error: {error.message}

              ; return (
              {JSON.stringify(data, null, 2)}
              ); }; export default DataComponent;

              总结

              自定义 Hook 允许你将组件逻辑提取到可复用的函数中,提高代码的可读性和维护性。通过自定义 Hook,可以更方便地复用逻辑、管理复杂的状态和副作用,从而简化组件代码。

VPS购买请点击我

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

目录[+]