1.實現功能(ts)
0.基礎屬性使用
1.組件直接的通信
2.useState 動態修改值
3.循環遍歷功能
4.實現類型vue 的 watch ,filter,computed 屬性功能
5.實現類似vue2的生命周期
5.類型vue v-if功能的實現
2.文件結構圖
3.具體代碼
interface.ts
import "./index.less";
import { message } from "antd";
import { useState, useEffect, useRef } from "react";
import { UserInfo } from "./interface";
import UserAge from "./components/UserAge"const UseComponent = () => {let [user, setUser] = useState<UserInfo>({ name: "張三", age: 5 });const [messageApi, contextHolder] = message.useMessage();let [show, setShow] = useState<boolean>(false);// 循環遍歷let [userList] = useState<UserInfo[]>([{ id: 1, name: "張三", age: 5 },{ id: 2, name: "李四", age: 10 },{ id: 3, name: "王五", age: 15 }]);const updateShow = () => {setShow(!show)}const updateAge = (updateAge: number, type: string = "add") => {let ageTemp: number = user.age;if (type === "add") {ageTemp = ageTemp + updateAge;} else if (type === "reduce") {ageTemp = ageTemp - updateAge;}if (ageTemp < 0) {messageApi.error("年齡不能小于0");ageTemp = 0;} else if (ageTemp > 100) {messageApi.error("年齡不能大于100");ageTemp = 100;}setUser(user => ({...user,age: ageTemp}));};const updateChild = (age: number) => {updateAge(age)}// 類型vue 的生命周期// Vue2 生命周期 | React 實現//---------------------------------------// beforeCreate => 無直接等價(可用 useRef 模擬)// created => useEffect 空依賴// beforeMount => useLayoutEffect 空依賴// mounted => useEffect 空依賴// beforeUpdate => useLayoutEffect 無依賴// updated => useEffect 無依賴// beforeDestroy => useEffect 返回清理函數// destroyed => useEffect 返回清理函數const UseComponent = () => {// beforeCreate 階段(組件初始化前)const initializedRef = useRef<boolean>(false);if (!initializedRef.current) {console.log("beforeCreate - 類似 Vue 的 beforeCreate");initializedRef.current = true;}// created 階段(組件初始化)useEffect(() => {console.log("created - 類似 Vue 的 created");}, []);// mounted 階段(DOM 掛載完成)useEffect(() => {console.log("mounted - 類似 Vue 的 mounted");}, []);// updated 階段(數據更新)useEffect(() => {console.log("updated - 類似 Vue 的 updated");});// beforeDestroy 階段(組件卸載前)useEffect(() => {return () => {console.log("beforeDestroy - 類似 Vue 的 beforeDestroy");};}, []);}UseComponent()return (<>{contextHolder}<div className="card content-box"><div>姓名:{user.name}</div><div>年齡:{user.age}</div><div className="flex-btn"><button className="add-btn" onClick={() => updateAge(1)}>年齡+1</button><button className="add-btn" onClick={() => updateAge(1, "reduce")}>年齡-1</button><button className="add-btn" onClick={() => updateShow()}>{!show ? "顯示" : '隱藏'}</button></div><div className="child"><div>我是子組件</div>{show && <UserAge user={user} updateChild={updateChild} />}</div><div>{userList.map((item, index) => {return (<div key={index}><div>姓名:{item.name}</div><div>年齡:{item.age}</div><div>------------------</div></div>)})}</div></div></>);
};export default UseComponent;
interface.ts
// 定義屬性 ?代表可填可不填
export interface UserInfo {id?: number;name: string;age: number;
}
UserAge.tsx
import React from "react";
import { UserInfo } from "../interface";interface Props {user: UserInfo;updateChild: (num: number) => void;
}const UserAge: React.FC<Props> = (props) => {//獲取父組件的參數// 類似 vue 的 watch React.useEffect(() => {console.log("子組件渲染", props.user);}, [props.user]);// 類似 vue 的 computedconst ageStatus: string = React.useMemo(() => {return props.user.age > 20 ? '中年' : '少年'}, [props.user.age]);// 類似vue 的 filter 也可以使用自定義hook的方式實現const ageFilter = (age: number) => {return age + "歲"}// 向父組件傳遞參數const updateFan = () => {props.updateChild(5);};return (<><div>我是子組件的age: {ageFilter(props.user.age)} {ageStatus}</div><button onClick={updateFan}>子組件控制父組件</button></>);
}export default UserAge;