React 基础

发布于:2025-09-12 ⋅ 阅读:(22) ⋅ 点赞:(0)

对比学习react, 以vue 为例
Vue3 的双向绑定: state.xxx = xxx => Proxy set => trigger(触发更新) => effect (执行副作用函数) => 更新dom
React(类组件):onClick => dispatch => enqueueSetState(更新队列) => scheduleUpdateOnFiber(标记fiber节点,启动更新)
学习的时候尽量结合ts一起

  • 类组件与函数组件(函数组件的开发效率更高,用的也更多一些)

  • 类组件:

      interface AppState {
        name: string,
        value: string
      }
      class App extends React.Component<AppState> {
        state:AppState = {
          name:'react',
          value: '类组件'
        };
        render():React.ReactNode {
          return <div>{`我是${this.state.name + this.state.value}`}</div>
        }
      }
     ```
    
  • 函数组件:

      	interface AppState {
      	  name: string,
      	  value: string
      	}
      	const App = () => {
      	  const [myState, setState] = useState<AppState>({name: 'react', value : '函数组件'})
      	  return (
      	    <div className="content">
      	      <h1>Rsbuild with React</h1>
      	      <p>{`我是${myState.name + myState.value}`}</p>
      	    </div>
      	  );
      	};
    
  • 受控组件与非受控组件(以表单元素举例,自定义组件也适用)

    • 受控组件(指表单元素的值由React组件的state完全控制的组件)
      const App= () => {
        const [name, setName] = useState<string>('')
        const handleChange = ():void => {
          setName('张三')
        }
        return (
          <div className="content">
            <input value={name} onClick={handleChange}></input>
          </div>
        );
      };
      
    • 非受控组件(表单元素的值由DOM自身管理,而不是由React state控制的组件)
      const App= () => {
        const inputRef = useRef<HTMLInputElement>(null);
        const handleChange = ():void => {
          console.log(inputRef.current?.value)
        }
        return <div>
          <input ref={inputRef}></input>
          <button onClick={handleChange}>获取input值</button>
        </div>
      };
      
      
  • props 与 state

    interface PersonState {
      name: string,
      age: number,
    }
    interface PersonComProps {
      person: PersonState
    }
    //props 外部传入使用
    const PersonCom:React.FC<PersonComProps> = (props) => {
      return <div>
        <span>姓名: {props.person.name}</span>
        <span>年龄:{props.person.age}</span>
      </div>
    }
    const App= () => {
      //通过useState hooks 声明state
      const [person, setPerson] = useState<PersonState>({name: '张三',age: 18})
      const changePerson = ():void => {
         setPerson({name: '王五',age: 20})
      }
      return <div>
        <PersonCom person ={person}  />
        <button onClick={changePerson}>切换人物</button>
      </div>
    };
    
  • 条件渲染与列表(React 非常灵活,编写jsx的时候可以就当作我们在写js)

    	interface User {
    	  name: string
    	}
    	const App = () => {
    	  const [show, setShow] = useState<boolean>(true);
    	  const [list] = useState<User[]>([{name:'张三'},{name:'李四'},{name:'王五'}])
    	  const handleChange = (): void => {
    	    setShow(!show);
    	  };
    	  return (
    	    <div>
    	      {/* 三元判断渲染 */}
    	      <div>{show ? "展示这个" : "展示另一个"}</div>
    	      <button onClick={handleChange}>切换展示</button>
    	      {/* list循环渲染 */}
    	      {list.map((item,index) => <div key={index}>{item.name}</div>)}
    	    </div>
    	  );
    	};
    
  • React 生命周期(这里描述的是19版本的类组件; 函数组件大多数使用useEffect、useMemo等hooks模拟生命周期操作)

    • 挂载阶段
      • constructor (初始化数据)
        1. 调用 super(props) 继承React组件
        2. 初始化组件的state状态
        3. 为方法绑定this上下文(解决this指向问题)
        4. 创建ref引用等准备工作
      • static getDerivedStateFromProps(在渲染前根据新的props来更新state)
        1. 本质上是一个静态函数 传入state 和 props ,返回值会和当前的state 合并
      • render(渲染)
        1. 返回JSX描述UI结构
        2. 必须是纯函数,不能修改state或与DOM交互
        3. 准备虚拟DOM,为后续的DOM更新做准备
      • componentDidMount(组件挂载完成, 这里一般可以请求接口)
    • 更新阶段
      • static getDerivedStateFromProps
      • shouldComponentUpdate(是否应该更新)
        1. 比较新旧props和state
        2. 返回true允许更新,返回false阻止更新
        3. 性能优化操作
      • render
      • getSnapshotBeforeUpdate(获取更新前快照,React更新过程中会通过计算虚拟dom去更新真实dom,这使得我们会丢失一些想保存的状态,例如聊天室中当前的滚动位置,可以通过此声明周期将位置信息传给 componentDidUpdate)
        // 在聊天室中,新消息到来时保持当前滚动位置
        getSnapshotBeforeUpdate(prevProps, prevState) {
          if (prevProps.messages.length < this.props.messages.length) {
            // 捕获滚动容器的滚动高度
            return this.chatContainer.scrollHeight - this.chatContainer.scrollTop;
          }
          return null;
        }
        
        componentDidUpdate(prevProps, prevState, snapshot) {
          if (snapshot !== null) {
            // 根据之前计算的滚动位置调整UI
            this.chatContainer.scrollTop = this.chatContainer.scrollHeight - snapshot;
          }
        }
        
      • componentDidUpdate(更新完成)
    • 卸载阶段
      • componentWillUnmount(组件将要卸载)
        1. 事件监听函数/定时器的销毁操作
      • static getDerivedStateFromError (捕获子组件的渲染错误)
      • componentDidCatch (捕获子组件的js错误)
        1. 异常兜底操作,防止白屏
  • React 事件相关

    • 阻止默认事件: e.preventDefault();
    • 阻止事件传播: stopPropagation();
    • dom绑定事件
      const handleListen = (): void => {
      console.log('focus了')
        };
      useEffect(() => {
        inputRef.current?.addEventListener("focus", handleListen);
        return () => {
          inputRef?.current?.removeEventListener("focus", handleListen);
        };
      }, []);
    
    • 自定义DOM事件
      • 使用new CustomEvent来创建自定义事件
      • 使用document.dispatchEvent 触发自定义事件
    const App = () => {
      //自定义事件hooks
      const useCustomEvent = (eventName: string, detail: any) => {
        const dispathEvent = useCallback(
          (customDetail?: any) => {
            const event = new CustomEvent(eventName, {
              detail: customDetail || detail,
            });
            document.dispatchEvent(event);
          },
          [eventName, detail]
        );
        return dispathEvent;
      };
      const dispathMyEvent = useCustomEvent("myEvent", "hello word");
      const handleMyEvent = (): void => {
        console.log("触发了自定义事件");
      };
      useEffect(() => {
        //监听事件
        document.addEventListener("myEvent", handleMyEvent);
        return () => {
          document.removeEventListener("myEvent", handleMyEvent);
        };
      }, []);
      return (
        <div>
          {/* //触发自定义事件 */}
          <button onClick={() => dispathMyEvent()}>触发自定义事件</button>
        </div>
      );
    };
    
    

网站公告

今日签到

点亮在社区的每一天
去签到