什么是 ahooks?
ahooks 是一个 React Hooks 库,提供了大量实用的自定义 hooks,帮助开发者更高效地构建 React 应用。其中场景类 hooks 是 ahooks 的一个重要分类,专门针对特定业务场景提供解决方案。
安装 ahooks
npm install ahooks
场景类 hook 详解
useAntdTable – Antd 表格集成
useAntdTable
用于处理表格与表单的联动场景。
import React from "react";
import { useAntdTable } from "ahooks";
import { Form, Input, Button, Table } from "antd";const UserTable = () => {const [form] = Form.useForm();const { tableProps, search } = useAntdTable(async (params, form) => {const { current, pageSize } = params;const response = await fetch("/api/users", {method: "POST",body: JSON.stringify({page: current,size: pageSize,...form,}),});const data = await response.json();return {list: data.list,total: data.total,};},{form,defaultPageSize: 10,});return (<div className="container m-4"><Form form={form} layout="inline" className="mb-2"><Form.Item name="name" label="姓名"><Input placeholder="请输入姓名" /></Form.Item><Form.Item name="email" label="邮箱"><Input placeholder="请输入邮箱" /></Form.Item><Form.Item><Button type="primary" onClick={search.submit}>搜索</Button><Button onClick={search.reset} style={{ marginLeft: 8 }}>重置</Button></Form.Item></Form><Table{...tableProps}columns={[{ title: "姓名", dataIndex: "name" },{ title: "邮箱", dataIndex: "email" },{ title: "创建时间", dataIndex: "createTime" },]}/></div>);
};
useFusionTable – Fusion 表格集成
useFusionTable
用于处理表格与表单的联动场景。
import React from "react";
import { useFusionTable } from "ahooks";
import { Table, Button, Input } from "@alifd/next";const UserTable = () => {const { tableProps, search, loading } = useFusionTable(async (params) => {const { current, pageSize, ...rest } = params;const response = await fetch("/api/users", {method: "POST",headers: { "Content-Type": "application/json" },body: JSON.stringify({page: current,size: pageSize,...rest,}),});const data = await response.json();return {list: data.list,total: data.total,};},{defaultPageSize: 10,defaultParams: [{ current: 1, pageSize: 10 }],});return (<div><div style={{ marginBottom: 16 }}><Inputplaceholder="搜索用户名"onChange={(value) => search.setFieldValue("name", value)}style={{ width: 200, marginRight: 8 }}/><Button type="primary" onClick={search.submit}>搜索</Button><Button onClick={search.reset} style={{ marginLeft: 8 }}>重置</Button></div><Table {...tableProps} loading={loading}><Table.Column title="姓名" dataIndex="name" /><Table.Column title="邮箱" dataIndex="email" /><Table.Column title="创建时间" dataIndex="createTime" /></Table></div>);
};
useInfiniteScroll – 无限滚动
import React from "react";
import { useInfiniteScroll } from "ahooks";const InfiniteList = () => {const { data, loading, noMore } = useInfiniteScroll(async (d) => {const { list = [], total = 0 } = await fetchData(d?.list?.length || 0);return {list: [...(d?.list || []), ...list],total,};},{target: document,isNoMore: (d) => d?.list?.length >= d?.total,threshold: 100,});return (<div style={{ height: "100vh", overflow: "auto" }}>{data?.list?.map((item, index) => (<divkey={`${item.id}-${index}`}style={{padding: "12px",borderBottom: "1px solid #eee",backgroundColor: index % 2 === 0 ? "#f9f9f9" : "white",}}><h3>{item.title}</h3><p>{item.description}</p></div>))}{loading && (<div style={{ textAlign: "center", padding: "20px" }}>加载中...</div>)}{noMore && (<div style={{ textAlign: "center", padding: "20px", color: "#999" }}>没有更多数据了</div>)}</div>);
};// 模拟数据获取函数
const fetchData = async (offset = 0) => {// 模拟API调用await new Promise((resolve) => setTimeout(resolve, 1000));const pageSize = 10;const mockData = Array.from({ length: pageSize }, (_, i) => ({id: offset + i,title: `项目 ${offset + i + 1}`,description: `这是第 ${offset + i + 1} 个项目的描述`,}));return {list: mockData,total: 50, // 总共50条数据};
};export default InfiniteList;
usePagination – 分页管理
import React from "react";
import { usePagination } from "ahooks";
import { Button, Input } from "antd";const PaginationExample = () => {const { data, loading, pagination, run } = usePagination(async ({ current, pageSize }) => {const response = await fetch(`/api/users?page=${current}&size=${pageSize}`);return response.json();},{defaultPageSize: 5,defaultCurrent: 1,});const [searchValue, setSearchValue] = React.useState("");const handleSearch = () => {run({ current: 1, pageSize: pagination.pageSize, search: searchValue });};return (<div><div style={{ marginBottom: 16 }}><Inputplaceholder="搜索用户"value={searchValue}onChange={(e) => setSearchValue(e.target.value)}style={{ width: 200, marginRight: 8 }}onPressEnter={handleSearch}/><Button type="primary" onClick={handleSearch}>搜索</Button></div>{loading ? (<div>加载中...</div>) : (<div>{data?.list?.map((user) => (<divkey={user.id}style={{padding: "8px",border: "1px solid #ddd",marginBottom: "8px",}}><strong>{user.name}</strong> - {user.email}</div>))}<div style={{ marginTop: 16 }}><Buttondisabled={pagination.current === 1}onClick={() => pagination.changeCurrent(pagination.current - 1)}>上一页</Button><span style={{ margin: "0 16px" }}>第 {pagination.current} 页,共 {pagination.total} 条</span><Buttondisabled={pagination.current >= pagination.totalPages}onClick={() => pagination.changeCurrent(pagination.current + 1)}>下一页</Button></div></div>)}</div>);
};
useDynamicList – 动态列表
import React from "react";
import { useDynamicList } from "ahooks";
import { Button, Input, Card } from "antd";const DynamicListExample = () => {const { list, remove, getKey, insert, move, replace, reset } = useDynamicList([{ name: "张三", age: 25 },{ name: "李四", age: 30 },{ name: "王五", age: 28 },]);const [inputName, setInputName] = React.useState("");const [inputAge, setInputAge] = React.useState("");const handleAdd = () => {if (inputName && inputAge) {insert(0, { name: inputName, age: parseInt(inputAge) });setInputName("");setInputAge("");}};return (<div><div style={{ marginBottom: 16 }}><Inputplaceholder="姓名"value={inputName}onChange={(e) => setInputName(e.target.value)}style={{ width: 120, marginRight: 8 }}/><Inputplaceholder="年龄"value={inputAge}onChange={(e) => setInputAge(e.target.value)}style={{ width: 80, marginRight: 8 }}/><Button type="primary" onClick={handleAdd}>添加到开头</Button><Button onClick={reset} style={{ marginLeft: 8 }}>重置</Button></div>{list.map((item, index) => (<Cardkey={getKey(index)}size="small"style={{ marginBottom: 8 }}extra={<div><Buttonsize="small"onClick={() => move(index, index - 1)}disabled={index === 0}>上移</Button><Buttonsize="small"onClick={() => move(index, index + 1)}disabled={index === list.length - 1}style={{ marginLeft: 4 }}>下移</Button><Buttonsize="small"dangeronClick={() => remove(index)}style={{ marginLeft: 4 }}>删除</Button></div>}><p><strong>姓名:</strong> {item.name}</p><p><strong>年龄:</strong> {item.age}</p></Card>))}</div>);
};
useVirtualList – 虚拟列表
import React, { useMemo, useRef } from "react";
import { useVirtualList } from "ahooks";export default function Demo() {const containerRef = useRef(null);const wrapperRef = useRef(null);// 生成大量测试数据const originalList = useMemo(() => {return Array.from({ length: 10000 }, (_, index) => ({id: index,title: `列表项 ${index + 1}`,content: `这是第 ${index + 1} 个列表项的内容,包含一些示例文本。`,timestamp: new Date(Date.now() - Math.random() * 10000000000).toLocaleString(),}));}, []);// 使用 useVirtualList hook - 正确版本const [list] = useVirtualList(originalList, {containerTarget: containerRef,wrapperTarget: wrapperRef,itemHeight: 80,overscan: 10,});console.log("originalList length:", originalList.length);console.log("virtual list length:", list.length);console.log("containerRef:", containerRef);console.log("wrapperRef:", wrapperRef);// 计算总高度const totalHeight = originalList.length * 80; // 每个项目80px高度console.log("totalHeight:", totalHeight);console.log("list first item:", list?.[0]);// 如果虚拟列表不工作,先显示普通列表const showNormalList = !list || list.length === 0;return (<div className="p-6 max-w-4xl mx-auto"><h1 className="text-3xl font-bold text-gray-800 mb-6">useVirtualList 虚拟列表示例</h1><div className="mb-4 text-sm text-gray-600">总共 {originalList.length} 个列表项,但只渲染可见区域的项目{showNormalList && (<span className="text-orange-600"> (使用普通列表作为备用)</span>)}</div>{/* 虚拟列表容器 */}<divref={containerRef}className="border border-gray-200 rounded-lg overflow-y-auto bg-white shadow-sm"style={{ height: "600px" }}><div ref={wrapperRef}>{showNormalList? // 备用:普通列表originalList.slice(0, 20).map((item) => (<divkey={item.id}className="border-b border-gray-100 p-4 hover:bg-gray-50 transition-colors"style={{ height: "80px" }}><div className="flex items-center justify-between"><div className="flex-1"><h3 className="font-semibold text-gray-800 mb-1">{item.title}</h3><p className="text-sm text-gray-600 line-clamp-2">{item.content}</p></div><div className="text-xs text-gray-400 ml-4">{item.timestamp}</div></div></div>)): // 虚拟列表list.map((item) => (<divkey={item.index}className="border-b border-gray-100 p-4 hover:bg-gray-50 transition-colors"style={{ height: "80px" }}><div className="flex items-center justify-between"><div className="flex-1"><h3 className="font-semibold text-gray-800 mb-1">{item.data.title}</h3><p className="text-sm text-gray-600 line-clamp-2">{item.data.content}</p></div><div className="text-xs text-gray-400 ml-4">{item.data.timestamp}</div></div></div>))}</div></div></div>);
}
6. useHistoryTravel – 历史记录
import React from "react";
import { useHistoryTravel } from "ahooks";
import { Button, Input, Card } from "antd";const HistoryTravelExample = () => {const { value, setValue, backLength, forwardLength, back, forward, reset } =useHistoryTravel("");const handleChange = (e) => {setValue(e.target.value);};return (<div><Card title="历史记录管理" style={{ marginBottom: 16 }}><div style={{ marginBottom: 16 }}><Inputvalue={value}onChange={handleChange}placeholder="输入内容,每次修改都会记录历史"style={{ marginBottom: 8 }}/><div><Button onClick={reset} style={{ marginRight: 8 }}>重置</Button><span style={{ color: "#666" }}>当前值: {value || "(空)"}</span></div></div><div style={{ marginBottom: 16 }}><Buttondisabled={backLength <= 0}onClick={back}style={{ marginRight: 8 }}>后退 ({backLength})</Button><Buttondisabled={forwardLength <= 0}onClick={forward}style={{ marginRight: 8 }}>前进 ({forwardLength})</Button></div></Card><Card title="历史记录信息"><p><strong>可后退步数:</strong> {backLength}</p><p><strong>可前进步数:</strong> {forwardLength}</p><p><strong>总历史记录数:</strong> {backLength + forwardLength + 1}</p></Card></div>);
};
useNetwork – 网络状态
import React from "react";
import { useNetwork } from "ahooks";
import { Card, Tag, Alert } from "antd";const NetworkExample = () => {const network = useNetwork();const getNetworkStatus = () => {if (network.online) {return <Tag color="green">在线</Tag>;}return <Tag color="red">离线</Tag>;};const getNetworkType = () => {if (network.effectiveType) {return <Tag color="blue">{network.effectiveType}</Tag>;}return <Tag color="orange">未知</Tag>;};return (<div><Card title="网络状态监控"><div style={{ marginBottom: 16 }}><strong>连接状态:</strong> {getNetworkStatus()}</div><div style={{ marginBottom: 16 }}><strong>网络类型:</strong> {getNetworkType()}</div>{!network.online && (<Alertmessage="网络连接已断开"description="请检查您的网络连接,某些功能可能无法正常使用。"type="warning"showIconstyle={{ marginBottom: 16 }}/>)}<Card title="详细网络信息" size="small"><p><strong>在线状态:</strong> {network.online ? "是" : "否"}</p><p><strong>网络类型:</strong> {network.effectiveType || "未知"}</p><p><strong>下行速度:</strong>{" "}{network.downlink ? `${network.downlink} Mbps` : "未知"}</p><p><strong>往返时间:</strong>{" "}{network.rtt ? `${network.rtt} ms` : "未知"}</p><p><strong>保存数据模式:</strong> {network.saveData ? "是" : "否"}</p></Card></Card></div>);
};
useSelections – 多选管理
import React, { useMemo } from "react";
import { useSelections } from "ahooks";
import { Checkbox, Button, Card, List } from "antd";const SelectionsExample = () => {const list = useMemo(() => [{ id: 1, name: "苹果", price: 5.5 },{ id: 2, name: "香蕉", price: 3.2 },{ id: 3, name: "橙子", price: 4.8 },{ id: 4, name: "葡萄", price: 8.9 },{ id: 5, name: "草莓", price: 12.5 },{ id: 6, name: "蓝莓", price: 15.8 },],[]);const {selected,allSelected,isSelected,toggle,toggleAll,partiallySelected,} = useSelections(list, {defaultSelected: [list[0], list[2]], // 默认选中第一个和第三个项});const totalPrice = selected.map((item) => item.price || 0).reduce((sum, price) => sum + price, 0);// 调试信息console.log("selected:", selected);console.log("allSelected:", allSelected);console.log("partiallySelected:", partiallySelected);console.log("list:", list);return (<div><divstyle={{marginBottom: 16,padding: "10px",backgroundColor: "#f5f5f5",borderRadius: "4px",}}><strong>当前选中项 ID:</strong>{" "}{selected.map((item) => item.id).join(", ") || "无"}</div><Card title="多选管理示例" style={{ marginBottom: 16 }}><div style={{ marginBottom: 16 }}><Checkboxchecked={allSelected}onClick={toggleAll}indeterminate={partiallySelected}style={{ marginRight: 8 }}>全选</Checkbox><span style={{ color: "#666" }}>已选择 {selected.length} 项,总价: ¥{totalPrice.toFixed(2)}</span></div><ListdataSource={list}renderItem={(item) => (<List.Itemstyle={{display: "flex",justifyContent: "space-between",alignItems: "center",padding: "8px 0",borderBottom: "1px solid #f0f0f0",}}><div style={{ display: "flex", alignItems: "center" }}><Checkboxchecked={isSelected(item)}onClick={() => toggle(item)}style={{ marginRight: 8 }}/><span>{item.name}</span></div><span style={{ color: "#666" }}>¥{item.price}</span></List.Item>)}/></Card></div>);
};
useCountDown – 倒计时
import React, { useState } from "react";
import { useCountDown } from "ahooks";
import { Button, Card, Input, message } from "antd";const SmsCountDownExample = () => {const [phoneNumber, setPhoneNumber] = useState("");const [targetDate, setTargetDate] = useState();const [countdown] = useCountDown({targetDate,onEnd: () => {console.log("倒计时结束!");message.success("倒计时结束,可以重新发送短信");},});const formatTime = (ms) => {const seconds = Math.floor(ms / 1000);return seconds.toString().padStart(2, "0");};const handleSendSms = () => {if (!phoneNumber) {message.error("请输入手机号码");return;}if (phoneNumber.length !== 11) {message.error("请输入正确的11位手机号码");return;}// 模拟发送短信message.success(`验证码已发送到 ${phoneNumber}`);// 开始60秒倒计时setTargetDate(Date.now() + 60000);};const handleReset = () => {setTargetDate(undefined);};return (<div><Card title="短信验证码倒计时" style={{ marginBottom: 16 }}><div style={{ marginBottom: 16 }}><Inputplaceholder="请输入手机号码"value={phoneNumber}onChange={(e) => setPhoneNumber(e.target.value)}style={{ marginBottom: 8 }}maxLength={11}/><div style={{ display: "flex", alignItems: "center", gap: 8 }}><Buttontype="primary"onClick={handleSendSms}disabled={countdown !== 0}style={{ flex: 1 }}>{countdown === 0? "发送验证码": `重新发送(${formatTime(countdown)}s)`}</Button>{countdown !== 0 && (<Button onClick={handleReset} size="small">重置</Button>)}</div></div></Card></div>);
};
useCounter – 计数器
import React from "react";
import { useCounter } from "ahooks";
import { Button, Card, InputNumber, Space } from "antd";const CounterExample = () => {const [current, { inc, dec, set, reset }] = useCounter(1, {min: 1,max: 10,});return (<div><Card title="useCounter 计数器示例" style={{ marginBottom: 16 }}><div style={{ textAlign: "center", marginBottom: 16 }}><divstyle={{ fontSize: "32px", fontWeight: "bold", color: "#1890ff" }}>{current}</div></div><div style={{ textAlign: "center", marginBottom: 16 }}><Space><Buttontype="primary"onClick={() => inc()}style={{ marginRight: 8 }}>inc(1)</Button><Button onClick={() => dec()} style={{ marginRight: 8 }}>dec(1)</Button><Button onClick={() => set(3)} style={{ marginRight: 8 }}>set(3)</Button><Button onClick={reset} style={{ marginRight: 8 }}>reset(0)</Button></Space></div><div style={{ textAlign: "center" }}><Space><InputNumbermin={1}max={10}value={current}onChange={(value) => set(value || 1)}style={{ width: 100 }}/><span style={{ color: "#666" }}>直接输入数值</span></Space></div></Card></div>);
};
useTextSelection – 文本选择
import React from "react";
import { useTextSelection } from "ahooks";
import { Card } from "antd";const TextSelectionExample = () => {const selection = useTextSelection();return (<div><Card title="文本选择监听" style={{ marginBottom: 16 }}><divstyle={{padding: "16px",border: "1px solid #d9d9d9",borderRadius: "6px",backgroundColor: "#fafafa",lineHeight: "1.8",}}><p>这是一段示例文本,您可以在这里选择任意内容。选择文本后,下方会显示选择的相关信息,包括选中的文本内容、选择的位置信息等。这个功能在需要获取用户选择的文本内容时非常有用,比如实现文本高亮、复制选中内容等功能。</p><p>您可以尝试选择单个单词、短语或者整段文本,观察下方信息的变化。选择不同的文本内容,会得到不同的选择结果。</p></div></Card><Card title="选择信息" size="small" style={{ marginBottom: 16 }}>{selection.text ? (<div><p><strong>选中的文本:</strong></p><divstyle={{padding: "8px",backgroundColor: "#f0f0f0",borderRadius: "4px",marginBottom: "8px",wordBreak: "break-all",}}>"{selection.text}"</div>{selection.rects && selection.rects.length > 0 && (<div><p><strong>选择区域:</strong></p><div style={{ fontSize: "12px", color: "#666" }}><p>区域数量: {selection.rects.length}</p>{selection.rects.map((rect, index) => (<p key={index}>区域 {index + 1}: x={rect.x.toFixed(0)}, y={rect.y.toFixed(0)}, 宽={rect.width.toFixed(0)}, 高={rect.height.toFixed(0)}</p>))}</div></div>)}</div>) : (<div style={{ color: "#999", textAlign: "center" }}>请在上方文本中选择内容</div>)}</Card></div>);
};
useWebSocket – WebSocket 连接
import React, { useState } from "react";
import { useWebSocket } from "ahooks";
import { Button, Card, Input, List, Tag, Alert } from "antd";const WebSocketExample = () => {const [url, setUrl] = useState("ws://localhost:8080");const [message, setMessage] = useState("");const { readyState, sendMessage, latestMessage, disconnect, connect } =useWebSocket(url, {onOpen: () => {console.log("WebSocket连接成功");},onMessage: (message) => {console.log("收到消息:", message);},onError: (error) => {console.log("WebSocket错误:", error);},onClose: () => {console.log("WebSocket连接关闭");},manual: true, // 手动连接});const [messageHistory, setMessageHistory] = useState([]);React.useEffect(() => {if (latestMessage) {setMessageHistory((prev) => [...prev,{id: Date.now(),content: latestMessage.data,type: "received",time: new Date().toLocaleTimeString(),},]);}}, [latestMessage]);const handleSend = () => {if (message.trim()) {sendMessage(message);setMessageHistory((prev) => [...prev,{id: Date.now(),content: message,type: "sent",time: new Date().toLocaleTimeString(),},]);setMessage("");}};const getStatusText = () => {switch (readyState) {case 0:return { text: "连接中", color: "processing" };case 1:return { text: "已连接", color: "success" };case 2:return { text: "关闭中", color: "warning" };case 3:return { text: "已关闭", color: "error" };default:return { text: "未知", color: "default" };}};const status = getStatusText();return (<div><Card title="WebSocket 连接管理" style={{ marginBottom: 16 }}><div style={{ marginBottom: 16 }}><Inputvalue={url}onChange={(e) => setUrl(e.target.value)}placeholder="WebSocket URL"style={{ marginBottom: 8 }}/><div><Buttontype="primary"onClick={connect}disabled={readyState === 1}style={{ marginRight: 8 }}>连接</Button><ButtononClick={disconnect}disabled={readyState !== 1}style={{ marginRight: 8 }}>断开</Button><Tag color={status.color}>状态: {status.text}</Tag></div></div>{readyState === 3 && (<Alertmessage="连接已断开"description="请点击连接按钮重新建立WebSocket连接"type="warning"showIconstyle={{ marginBottom: 16 }}/>)}</Card><Card title="消息收发" style={{ marginBottom: 16 }}><div style={{ marginBottom: 16 }}><Input.TextAreavalue={message}onChange={(e) => setMessage(e.target.value)}placeholder="输入要发送的消息"rows={3}style={{ marginBottom: 8 }}onPressEnter={(e) => {if (!e.shiftKey) {e.preventDefault();handleSend();}}}/><Buttontype="primary"onClick={handleSend}disabled={readyState !== 1 || !message.trim()}>发送消息</Button></div><Listsize="small"dataSource={messageHistory}renderItem={(item) => (<List.Itemstyle={{padding: "8px 0",borderBottom: "1px solid #f0f0f0",}}><div style={{ width: "100%" }}><divstyle={{display: "flex",justifyContent: "space-between",marginBottom: "4px",}}><Tag color={item.type === "sent" ? "blue" : "green"}>{item.type === "sent" ? "发送" : "接收"}</Tag><span style={{ fontSize: "12px", color: "#666" }}>{item.time}</span></div><divstyle={{padding: "8px",backgroundColor:item.type === "sent" ? "#e6f7ff" : "#f6ffed",borderRadius: "4px",wordBreak: "break-all",}}>{item.content}</div></div></List.Item>)}/></Card><Card title="连接信息" size="small"><p><strong>连接状态:</strong><Tag color={status.color}>{status.text}</Tag></p><p><strong>连接URL:</strong> {url}</p><p><strong>消息总数:</strong> {messageHistory.length}</p><p><strong>最后消息:</strong> {latestMessage?.data || "无"}</p></Card></div>);
};
useTheme – 主题
import React from "react";
import { useTheme } from "ahooks";
import { Button, Card, Tag } from "antd";const ThemeExample = () => {const { theme, themeMode, setThemeMode } = useTheme({localStorageKey: "themeMode",});return (<div><Card title="useTheme 基础用法" style={{ marginBottom: 16 }}><div style={{ marginBottom: 16 }}><p><strong>theme:</strong> <Tag color="blue">{theme}</Tag></p><p><strong>themeMode:</strong> <Tag color="green">{themeMode}</Tag></p></div><div style={{ marginBottom: 16 }}><Buttontype="primary"onClick={() => setThemeMode("dark")}style={{ marginRight: 8 }}>使用深色主题</Button><ButtononClick={() => setThemeMode("light")}style={{ marginRight: 8 }}>使用浅色主题</Button><ButtononClick={() => setThemeMode("system")}style={{ marginRight: 8 }}>跟随系统</Button></div><divstyle={{padding: "16px",border: "1px solid #d9d9d9",borderRadius: "6px",backgroundColor: theme === "dark" ? "#141414" : "#ffffff",color: theme === "dark" ? "#ffffff" : "#000000",transition: "all 0.3s ease",}}><h3 style={{ marginBottom: 12 }}>主题预览区域</h3><p>这是一个主题预览区域,展示了当前主题的样式效果。 当前主题: {theme},主题模式: {themeMode}</p></div></Card></div>);
};
通过合理使用这些 hooks,可以大大简化 React 应用的开发复杂度,提高代码的可维护性和用户体验。
场景类 hooks 速查表
Hook 名称 | 用途 | 描述 |
---|---|---|
useAntdTable | Antd 表格集成 | 专门为 Ant Design Table 组件设计的 hook,简化表格数据获取和分页管理 |
useFusionTable | Fusion 表格集成 | 专门为 Fusion Design Table 组件设计的 hook,提供表格数据管理功能 |
useInfiniteScroll | 无限滚动 | 实现无限滚动加载,支持触底加载更多数据,自动处理加载状态 |
usePagination | 分页管理 | 简化分页数据的获取和管理,自动处理页码和页面大小的状态 |
useDynamicList | 动态列表 | 管理动态增减的列表项,支持添加、删除、移动等操作 |
useVirtualList | 虚拟列表 | 实现大数据量的虚拟滚动列表,提升性能,减少 DOM 节点数量 |
useHistoryTravel | 历史记录 | 管理状态的历史记录,支持前进、后退、跳转到指定历史点 |
useNetwork | 网络状态 | 监听网络连接状态变化,包括在线/离线状态和网络类型 |
useSelections | 多选管理 | 管理列表的多选状态,支持全选、反选、批量操作等功能 |
useCountDown | 倒计时 | 实现倒计时功能,支持自定义格式和回调函数 |
useCounter | 计数器 | 管理数字计数器的增删改查操作,支持步长设置 |
useTextSelection | 文本选择 | 监听用户文本选择事件,获取选中的文本内容和位置信息 |
useWebSocket | WebSocket 连接 | 管理 WebSocket 连接,处理连接、断开、消息收发等操作 |
useTheme | 主题管理 | 管理应用主题状态,支持主题切换和持久化存储 |
React强大且灵活hooks库——ahooks入门实践之场景类(scene)hook详解 - 高质量源码分享平台-免费下载各类网站源码与模板及前沿动态资讯