Hooks 進階:自定義 Hook 的設計與實踐

引言

React Hooks 已成為現代 React 開發的核心范式,而自定義 Hook 則為我們提供了強大的代碼復用機制。

自定義 Hook 的基礎原理

自定義 Hook 本質上是一種函數復用機制,它允許我們將組件邏輯提取到可重用的函數中。與傳統的高階組件(HOC)和 render props 模式相比,Hook 提供了更直接的狀態共享方式,不會引入額外的組件嵌套。

自定義 Hook 的核心規則

  1. 命名必須以 use 開頭:這不僅是約定,也使 React 能夠識別 Hook 函數
  2. 可以調用其他 Hook:自定義 Hook 內部可以調用 React 內置 Hook 或其他自定義 Hook
  3. 狀態是隔離的:不同組件調用同一個 Hook 不會共享狀態
// 基礎自定義 Hook 示例
function useCounter(initialValue = 0, step = 1) {const [count, setCount] = useState(initialValue);const increment = useCallback(() => {setCount(prevCount => prevCount + step);}, [step]);const decrement = useCallback(() => {setCount(prevCount => prevCount - step);}, [step]);const reset = useCallback(() => {setCount(initialValue);}, [initialValue]);return { count, increment, decrement, reset };
}// 使用示例
function CounterComponent() {const { count, increment, decrement, reset } = useCounter(10, 2);return (<div><p>當前計數: {count}</p><button onClick={increment}>增加</button><button onClick={decrement}>減少</button><button onClick={reset}>重置</button></div>);
}

自定義 Hook 設計模式

1. 資源管理型 Hook

這類 Hook 負責管理外部資源的生命周期,如網絡請求、事件監聽等。

function useFetch(url, options = {}) {const [data, setData] = useState(null);const [loading, setLoading] = useState(true);const [error, setError] = useState(null);const optionsRef = useRef(options);useEffect(() => {let isMounted = true;const controller = new AbortController();const signal = controller.signal;const fetchData = async () => {setLoading(true);try {const response = await fetch(url, {...optionsRef.current,signal});if (!response.ok) {throw new Error(`HTTP error! Status: ${response.status}`);}const result = await response.json();if (isMounted) {setData(result);setError(null);}} catch (err) {if (isMounted && err.name !== 'AbortError') {setError(err.message);setData(null);}} finally {if (isMounted) {setLoading(false);}}};fetchData();return () => {isMounted = false;controller.abort();};}, [url]);return { data, loading, error };
}// 使用示例
function UserProfile({ userId }) {const { data: user, loading, error } = useFetch(`https://api.example.com/users/${userId}`);if (loading) return <div>加載中...</div>;if (error) return <div>錯誤: {error}</div>;return (<div><h2>{user.name}</h2><p>Email: {user.email}</p></div>);
}

2. 狀態邏輯型 Hook

封裝復雜狀態邏輯,提供簡潔的狀態管理接口。

function useForm(initialValues = {}) {const [values, setValues] = useState(initialValues);const [errors, setErrors] = useState({});const [touched, setTouched] = useState({});const [isSubmitting, setIsSubmitting] = useState(false);const handleChange = useCallback((e) => {const { name, value } = e.target;setValues(prev => ({...prev,[name]: value}));}, []);const handleBlur = useCallback((e) => {const { name } = e.target;setTouched(prev => ({...prev,[name]: true}));}, []);const reset = useCallback(() => {setValues(initialValues);setErrors({});setTouched({});setIsSubmitting(false);}, [initialValues]);return {values,errors,touched,isSubmitting,handleChange,handleBlur,setValues,setErrors,setIsSubmitting,reset};
}// 使用示例
function LoginForm() {const { values, errors, touched, isSubmitting, handleChange, handleBlur, setErrors, setIsSubmitting } = useForm({ email: '', password: '' });const validate = () => {const newErrors = {};if (!values.email) newErrors.email = '郵箱不能為空';if (!values.password) newErrors.password = '密碼不能為空';setErrors(newErrors);return Object.keys(newErrors).length === 0;};const handleSubmit = async (e) => {e.preventDefault();if (!validate()) return;setIsSubmitting(true);try {// 登錄邏輯await loginUser(values);alert('登錄成功');} catch (err) {setErrors({ form: err.message });} finally {setIsSubmitting(false);}};return (<form onSubmit={handleSubmit}><div><label htmlFor="email">郵箱</label><inputid="email"name="email"type="email"value={values.email}onChange={handleChange}onBlur={handleBlur}/>{touched.email && errors.email && <div className="error">{errors.email}</div>}</div><div><label htmlFor="password">密碼</label><inputid="password"name="password"type="password"value={values.password}onChange={handleChange}onBlur={handleBlur}/>{touched.password && errors.password && <div className="error">{errors.password}</div>}</div>{errors.form && <div className="error">{errors.form}</div>}<button type="submit" disabled={isSubmitting}>{isSubmitting ? '登錄中...' : '登錄'}</button></form>);
}

3. 行為型 Hook

封裝特定用戶交互行為的邏輯,如拖拽、虛擬滾動等。

function useDrag(ref, options = {}) {const {onDragStart,onDrag,onDragEnd,disabled = false} = options;const [isDragging, setIsDragging] = useState(false);const [position, setPosition] = useState({ x: 0, y: 0 });const startPosRef = useRef({ x: 0, y: 0 });const currentPosRef = useRef({ x: 0, y: 0 });useEffect(() => {if (!ref.current || disabled) return;const element = ref.current;const handleMouseDown = (e) => {// 避免與點擊事件沖突if (e.button !== 0) return;setIsDragging(true);startPosRef.current = {x: e.clientX - currentPosRef.current.x,y: e.clientY - currentPosRef.current.y};if (onDragStart) {onDragStart({x: currentPosRef.current.x,y: currentPosRef.current.y});}document.addEventListener('mousemove', handleMouseMove);document.addEventListener('mouseup', handleMouseUp);e.preventDefault();};const handleMouseMove = (e) => {if (!isDragging) return;const newPos = {x: e.clientX - startPosRef.current.x,y: e.clientY - startPosRef.current.y};currentPosRef.current = newPos;setPosition(newPos);if (onDrag) {onDrag(newPos);}};const handleMouseUp = () => {setIsDragging(false);document.removeEventListener('mousemove', handleMouseMove);document.removeEventListener('mouseup', handleMouseUp);if (onDragEnd) {onDragEnd({x: currentPosRef.current.x,y: currentPosRef.current.y});}};element.addEventListener('mousedown', handleMouseDown);return () => {element.removeEventListener('mousedown', handleMouseDown);document.removeEventListener('mousemove', handleMouseMove);document.removeEventListener('mouseup', handleMouseUp);};}, [ref, disabled, isDragging, onDragStart, onDrag, onDragEnd]);return { isDragging, position, setPosition };
}// 使用示例
function DraggableBox() {const boxRef = useRef(null);const { isDragging, position } = useDrag(boxRef, {onDragStart: (pos) => console.log('開始拖動', pos),onDragEnd: (pos) => console.log('結束拖動', pos)});return (<divref={boxRef}style={{position: 'absolute',left: `${position.x}px`,top: `${position.y}px`,width: '100px',height: '100px',background: isDragging ? '#5c7cfa' : '#339af0',cursor: 'grab',userSelect: 'none',boxShadow: isDragging ? '0 8px 16px rgba(0,0,0,0.2)' : '0 2px 4px rgba(0,0,0,0.1)',transition: isDragging ? 'none' : 'box-shadow 0.3s, background 0.3s'}}>拖拽我</div>);
}

高級技巧與優化

1. 依賴收集與性能優化

自定義 Hook 的性能優化主要關注兩個方面:減少不必要的重渲染和優化內部邏輯執行效率。

function useSearch(initialQuery = '') {const [query, setQuery] = useState(initialQuery);const [results, setResults] = useState([]);const [loading, setLoading] = useState(false);// 使用 useRef 保存最新值,避免 useCallback 和 useEffect 依賴過多const stateRef = useRef({ query });stateRef.current.query = query;// 使用 useCallback 緩存函數引用const search = useCallback(debounce(async () => {const currentQuery = stateRef.current.query;if (!currentQuery.trim()) {setResults([]);return;}setLoading(true);try {const response = await fetch(`https://api.example.com/search?q=${encodeURIComponent(currentQuery)}`);const data = await response.json();setResults(data);} catch (error) {console.error('搜索出錯:', error);setResults([]);} finally {setLoading(false);}}, 300), []);// 查詢變化時觸發搜索useEffect(() => {search();// 返回清理函數,取消正在進行的請求return () => {search.cancel();};}, [query, search]);return {query,setQuery,results,loading};
}// 節流/防抖輔助函數
function debounce(fn, delay) {let timer = null;const debounced = function(...args) {if (timer) clearTimeout(timer);timer = setTimeout(() => {fn.apply(this, args);}, delay);};debounced.cancel = function() {if (timer) {clearTimeout(timer);timer = null;}};return debounced;
}

2. 組合 Hooks 實現復雜功能

通過組合多個基礎 Hook 實現更復雜的功能,遵循單一職責原則。

// 基礎 Hook: 管理分頁狀態
function usePagination(initialPage = 1, initialPageSize = 10) {const [page, setPage] = useState(initialPage);const [pageSize, setPageSize] = useState(initialPageSize);const reset = useCallback(() => {setPage(initialPage);setPageSize(initialPageSize);}, [initialPage, initialPageSize]);return {page,pageSize,setPage,setPageSize,reset};
}// 基礎 Hook: 管理排序狀態
function useSorting(initialSortField = '', initialSortDirection = 'asc') {const [sortField, setSortField] = useState(initialSortField);const [sortDirection, setSortDirection] = useState(initialSortDirection);const toggleSort = useCallback((field) => {if (field === sortField) {setSortDirection(prev => prev === 'asc' ? 'desc' : 'asc');} else {setSortField(field);setSortDirection('asc');}}, [sortField]);return {sortField,sortDirection,toggleSort};
}// 組合 Hook: 實現數據表格功能
function useDataTable(fetchFn, initialFilters = {}) {const [filters, setFilters] = useState(initialFilters);const [data, setData] = useState([]);const [total, setTotal] = useState(0);const [loading, setLoading] = useState(false);const [error, setError] = useState(null);// 組合分頁 Hookconst pagination = usePagination();// 組合排序 Hookconst sorting = useSorting();// 加載數據的函數const loadData = useCallback(async () => {setLoading(true);setError(null);try {const params = {page: pagination.page,pageSize: pagination.pageSize,sortField: sorting.sortField,sortDirection: sorting.sortDirection,...filters};const result = await fetchFn(params);setData(result.data);setTotal(result.total);} catch (err) {setError(err.message);} finally {setLoading(false);}}, [fetchFn,pagination.page, pagination.pageSize, sorting.sortField, sorting.sortDirection, filters]);// 過濾條件、分頁或排序變化時重新加載數據useEffect(() => {loadData();}, [loadData]);// 更新過濾條件的函數const updateFilters = useCallback((newFilters) => {setFilters(prev => ({...prev,...newFilters}));// 重置到第一頁pagination.setPage(1);}, [pagination]);// 重置所有狀態const reset = useCallback(() => {pagination.reset();setFilters(initialFilters);}, [pagination, initialFilters]);return {// 數據狀態data,total,loading,error,// 分頁相關page: pagination.page,pageSize: pagination.pageSize,setPage: pagination.setPage,setPageSize: pagination.setPageSize,// 排序相關sortField: sorting.sortField,sortDirection: sorting.sortDirection,toggleSort: sorting.toggleSort,// 過濾相關filters,updateFilters,// 操作方法reload: loadData,reset};
}// 使用示例
function UsersTable() {const fetchUsers = async (params) => {const queryString = new URLSearchParams(params).toString();const response = await fetch(`https://api.example.com/users?${queryString}`);return await response.json();};const {data: users,total,loading,page,pageSize,setPage,setPageSize,sortField,sortDirection,toggleSort,filters,updateFilters} = useDataTable(fetchUsers, { status: 'active' });return (<div><div className="filters"><inputplaceholder="搜索用戶"value={filters.keyword || ''}onChange={e => updateFilters({ keyword: e.target.value })}/><selectvalue={filters.status}onChange={e => updateFilters({ status: e.target.value })}><option value="active">活躍</option><option value="inactive">非活躍</option><option value="all">全部</option></select></div>{loading ? (<div>加載中...</div>) : (<table><thead><tr><th onClick={() => toggleSort('name')}>姓名 {sortField === 'name' && (sortDirection === 'asc' ? '↑' : '↓')}</th><th onClick={() => toggleSort('email')}>郵箱 {sortField === 'email' && (sortDirection === 'asc' ? '↑' : '↓')}</th><th onClick={() => toggleSort('lastLogin')}>最近登錄 {sortField === 'lastLogin' && (sortDirection === 'asc' ? '↑' : '↓')}</th></tr></thead><tbody>{users.map(user => (<tr key={user.id}><td>{user.name}</td><td>{user.email}</td><td>{new Date(user.lastLogin).toLocaleString()}</td></tr>))}</tbody></table>)}<div className="pagination"><button disabled={page === 1} onClick={() => setPage(page - 1)}>上一頁</button><span>第 {page} 頁,共 {Math.ceil(total / pageSize)} 頁</span><button disabled={page >= Math.ceil(total / pageSize)}onClick={() => setPage(page + 1)}>下一頁</button><selectvalue={pageSize}onChange={e => setPageSize(Number(e.target.value))}><option value={10}>10條/頁</option><option value={20}>20條/頁</option><option value={50}>50條/頁</option></select></div></div>);
}

3. 利用 Context 優化 Hook 共享狀態

當多個組件需要共享同一個 Hook 的狀態時,可以結合 Context API 實現。

// 創建一個主題上下文
const ThemeContext = createContext(null);// 主題 Provider 組件
function ThemeProvider({ children, initialTheme = 'light' }) {const [theme, setTheme] = useState(initialTheme);// 在 localStorage 中保存主題偏好useEffect(() => {localStorage.setItem('theme', theme);}, [theme]);const toggleTheme = useCallback(() => {setTheme(prev => prev === 'light' ? 'dark' : 'light');}, []);// 創建主題值對象const themeValue = useMemo(() => ({theme,setTheme,toggleTheme,isDark: theme === 'dark'}), [theme, toggleTheme]);return (<ThemeContext.Provider value={themeValue}>{children}</ThemeContext.Provider>);
}// 自定義 Hook 用于訪問主題上下文
function useTheme() {const context = useContext(ThemeContext);if (context === null) {throw new Error('useTheme 必須在 ThemeProvider 內部使用');}return context;
}// 使用示例
function App() {return (<ThemeProvider initialTheme="light"><MainLayout /></ThemeProvider>);
}function MainLayout() {const { theme, toggleTheme } = useTheme();return (<div className={`app ${theme}`}><header><h1>我的應用</h1><button onClick={toggleTheme}>切換到{theme === 'light' ? '暗色' : '亮色'}主題</button></header><main><Content /></main></div>);
}function Content() {const { isDark } = useTheme();return (<section className="content"><h2>內容區域</h2><p>當前使用的是{isDark ? '暗色' : '亮色'}主題</p></section>);
}

自定義 Hook 與現代前端架構

1. 與狀態管理的整合

自定義 Hook 可以與 Redux、Zustand 等狀態管理庫無縫集成,提供更集中的狀態管理方案。

// 集成 Redux 的自定義 Hook
function useReduxActions(slice) {const dispatch = useDispatch();const state = useSelector(state => state[slice]);// 使用 useMemo 緩存創建的 actions 對象const actions = useMemo(() => {// 示例:為一個用戶模塊創建actionsif (slice === 'users') {return {fetchUsers: (params) => {dispatch({ type: 'users/fetchUsersStart', payload: params });return fetch(`/api/users?${new URLSearchParams(params)}`).then(res => res.json()).then(data => {dispatch({ type: 'users/fetchUsersSuccess', payload: data });return data;}).catch(error => {dispatch({ type: 'users/fetchUsersFailure', payload: error.message });throw error;});},createUser: (userData) => {dispatch({ type: 'users/createUserStart', payload: userData });return fetch('/api/users', {method: 'POST',headers: { 'Content-Type': 'application/json' },body: JSON.stringify(userData)}).then(res => res.json()).then(data => {dispatch({ type: 'users/createUserSuccess', payload: data });return data;}).catch(error => {dispatch({ type: 'users/createUserFailure', payload: error.message });throw error;});}};}return {};}, [dispatch, slice]);return { state, ...actions };
}// 使用示例
function UserList() {const { state: usersState, fetchUsers } = useReduxActions('users');const { data, loading, error } = usersState;useEffect(() => {fetchUsers({ page: 1, limit: 10 });}, [fetchUsers]);if (loading) return <div>加載中...</div>;if (error) return <div>錯誤: {error}</div>;return (<ul>{data.map(user => (<li key={user.id}>{user.name}</li>))}</ul>);
}

2. 與組件庫的協同設計

自定義 Hook 可以成為組件庫的強大輔助工具,為復雜組件提供邏輯層抽象。

// 自定義 Hook 和組件協同
function useMenuControl(initialOpenKeys = []) {const [openKeys, setOpenKeys] = useState(initialOpenKeys);const [selectedKey, setSelectedKey] = useState(null);const onOpenChange = useCallback((key) => {setOpenKeys(prev => {const keyIndex = prev.indexOf(key);if (keyIndex >= 0) {// 已打開,則關閉const newKeys = [...prev];newKeys.splice(keyIndex, 1);return newKeys;} else {// 未打開,則添加return [...prev, key];}});}, []);const isOpen = useCallback((key) => {return openKeys.includes(key);}, [openKeys]);return {openKeys,selectedKey,setSelectedKey,onOpenChange,isOpen};
}// 菜單組件
function Menu({ items, defaultOpenKeys = [] }) {const {openKeys,selectedKey,setSelectedKey,onOpenChange,isOpen} = useMenuControl(defaultOpenKeys);return (<nav className="menu">{items.map(item => {if (item.children) {return (<div key={item.key} className="submenu"><divclassName="submenu-title"onClick={() => onOpenChange(item.key)}>{item.icon && <span className="icon">{item.icon}</span>}<span>{item.label}</span><span className={`arrow ${isOpen(item.key) ? 'open' : ''}`}>?</span></div>{isOpen(item.key) && (<div className="submenu-items">{item.children.map(child => (<divkey={child.key}className={`menu-item ${selectedKey === child.key ? 'active' : ''}`}onClick={() => setSelectedKey(child.key)}>{child.icon && <span className="icon">{child.icon}</span>}<span>{child.label}</span></div>))}</div>)}</div>);}return (<divkey={item.key}className={`menu-item ${selectedKey === item.key ? 'active' : ''}`}onClick={() => setSelectedKey(item.key)}>{item.icon && <span className="icon">{item.icon}</span>}<span>{item.label}</span></div>);})}</nav>);
}// 使用示例
function SidebarNavigation() {const menuItems = [{key: 'dashboard',label: '儀表盤',icon: '📊'},{key: 'users',label: '用戶管理',icon: '👥',children: [{key: 'user-list',label: '用戶列表'},{key: 'user-groups',label: '用戶組'}]},{key: 'settings',label: '系統設置',icon: '??',children: [{key: 'profile',label: '個人資料'},{key: 'security',label: '安全設置'}]}];return (<div className="sidebar"><div className="logo">應用名稱</div><Menu items={menuItems} defaultOpenKeys={['users']} /></div>);
}

自定義 Hook 測試最佳實踐

測試自定義 Hook 是確保其可靠性和可維護性的關鍵環節。以下是針對自定義 Hook 的測試策略:

// 示例:使用 @testing-library/react-hooks 測試自定義 Hook// useCounter.js
import { useState, useCallback } from 'react';export function useCounter(initialValue = 0, step = 1) {const [count, setCount] = useState(initialValue);const increment = useCallback(() => {setCount(prevCount => prevCount + step);}, [step]);const decrement = useCallback(() => {setCount(prevCount => prevCount - step);}, [step]);const reset = useCallback(() => {setCount(initialValue);}, [initialValue]);return { count, increment, decrement, reset };
}// useCounter.test.js
import { renderHook, act } from '@testing-library/react-hooks';
import { useCounter } from './useCounter';describe('useCounter', () => {test('應該使用默認初始值', () => {const { result } = renderHook(() => useCounter());expect(result.current.count).toBe(0);});test('應該使用提供的初始值', () => {const { result } = renderHook(() => useCounter(10));expect(result.current.count).toBe(10);});test('應該遞增計數', () => {const { result } = renderHook(() => useCounter(0, 2));act(() => {result.current.increment();});expect(result.current.count).toBe(2);});test('應該遞減計數', () => {const { result } = renderHook(() => useCounter(10, 5));act(() => {result.current.decrement();});expect(result.current.count).toBe(5);});test('應該重置計數', () => {const { result } = renderHook(() => useCounter(10));act(() => {result.current.increment();result.current.reset();});expect(result.current.count).toBe(10);});test('當步長變化時應該更新遞增/遞減行為', () => {const { result, rerender } = renderHook(({ initialValue, step }) => useCounter(initialValue, step),{ initialProps: { initialValue: 0, step: 1 } });act(() => {result.current.increment();});expect(result.current.count).toBe(1);// 更新 step 參數rerender({ initialValue: 0, step: 3 });act(() => {result.current.increment();});expect(result.current.count).toBe(4); // 1 + 3});
});

實際項目應用

在實際項目中應用自定義 Hook 時,應采取以下建議:

  1. 職責單一:每個 Hook 應專注于單一功能,避免過度復雜
  2. 明確的命名:使用描述性的名稱清晰表達 Hook 的用途
  3. 文檔完善:為每個 Hook 編寫詳細文檔,包括參數、返回值和使用示例
  4. 版本控制:隨著 API 的演進,保持版本兼容性并提供遷移路徑
  5. 優先考慮性能:使用 useCallback、useMemo 優化 Hook 內部邏輯

結語

自定義 Hook 是 React 應用開發中強大的抽象工具,能夠顯著提升代碼復用性和可維護性。

未來,隨著 React 生態的不斷發展,自定義 Hook 的設計模式也將繼續演進。保持學習新的模式和技術,才能幫助我們在前端開發領域保持競爭力。

參考資源

官方文檔

  • React 官方文檔 - Hooks 介紹
  • React 官方文檔 - 自定義 Hook
  • React API 參考 - Hooks

技術博客和文章

  • Dan Abramov: Making Sense of React Hooks
  • Kent C. Dodds: The State Reducer Pattern with React Hooks
  • Robin Wieruch: React Hooks Tutorial
  • Tanner Linsley: React Query - 重新思考數據獲取的自定義 Hook

測試資源

  • React Testing Library 官方文檔
  • Testing React Hooks
  • @testing-library/react-hooks 使用指南

社區討論

  • React Hooks RFC 討論
  • StackOverflow: React Hooks 問答
  • React Subreddit

高級模式和實踐

  • React Patterns: 組合與自定義 Hooks
  • React Recipes: 常用自定義 Hook 實現
  • Josh W. Comeau: 使用 useSound Hook 增強用戶體驗

如果你覺得這篇文章有幫助,歡迎點贊收藏,也期待在評論區看到你的想法和建議!👇

終身學習,共同成長。

咱們下一期見

💻

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/84715.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/84715.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/84715.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

鋰電電動扭剪扳手市場報告:現狀、趨勢與競爭格局深度解析

一、鋰電電動扭剪扳手市場概述 鋰電電動扭剪扳手作為建筑施工、鋼結構安裝等領域的關鍵工具&#xff0c;憑借其便攜性、高效性及環保特性&#xff0c;正逐步替代傳統手動及氣動工具。該設備通過鋰電池供電&#xff0c;結合智能扭矩控制技術&#xff0c;可精準完成高強度螺栓的…

[面試精選] 0076. 最小覆蓋子串

文章目錄 1. 題目鏈接2. 題目描述3. 題目示例4. 解題思路5. 題解代碼6. 復雜度分析 1. 題目鏈接 76. 最小覆蓋子串 - 力扣&#xff08;LeetCode&#xff09; 2. 題目描述 給你一個字符串 s 、一個字符串 t 。返回 s 中涵蓋 t 所有字符的最小子串。如果 s 中不存在涵蓋 t 所有字…

rabbitmq的高級特性

一.發送者的可靠性 1.生產者重試機制 修改publisher模塊的application.yaml文件 spring:rabbitmq:connection-timeout: 1s # 設置MQ的連接超時時間template:retry:enabled: true # 開啟超時重試機制initial-interval: 1000ms # 失敗后的初始等待時間multiplier: 1 # 失敗后下…

北京大學肖臻老師《區塊鏈技術與應用》公開課:02-BTC-密碼學原理

文章目錄 1.比特幣中用到的密碼學的功能2. hash3. 簽名 1.比特幣中用到的密碼學的功能 比特幣中用到密碼學中兩個功能&#xff1a; hash、 簽名。 2. hash hash函數的三個特性&#xff1a;抗碰撞性&#xff08;Collision Resistance&#xff09;、隱蔽性&#xff08;Hiding&…

Spring Cloud Gateway高并發限流——基于Redis實現方案解析

本文是一個基于 Spring Cloud Gateway 的分布式限流方案&#xff0c;使用Redis Lua實現高并發場景下的精準流量控制。該方案支持動態配置、多維度限流&#xff08;API路徑/IP/用戶&#xff09;&#xff0c;并包含完整的代碼實現和性能優化建議。 一、架構設計 #mermaid-svg-vg…

SpringAI--RAG知識庫

SpringAI–RAG知識庫 RAG概念 什么是RAG&#xff1f; RAG(Retrieval-Augmented Genreation&#xff0c;檢索增強生成)是一種結合信息檢索技術和AI內容生成的混合架構&#xff0c;可以解決大模型的知識時效性限制和幻覺問題。 RAG在大語言模型生成回答之前&#xff0c;會先從…

【PhysUnits】14 二進制數的標準化表示(standardization.rs)

一、源碼 這段代碼主要用于處理二進制數的標準化表示。它定義了兩個特質(trait) IfB0 和 IfB1&#xff0c;以及它們的實現&#xff0c;用于處理二進制數的前導零及前導一的簡化。 use super::basic::{B0, B1, Z0, N1, Integer, NonZero, NonNegOne};/// 處理 B0<H> 類型…

將 ubutun 的網絡模式 從NAT 改到 橋接模式后,無法上網,linux 沒有IP地址 的解決方案

首先要將 ubutun 的網絡模式設置為橋接模式 這里再從 NAT 模式改動成 橋接模式的時候&#xff0c;還出現了一個問題。改成橋接模式后&#xff0c;linux沒有ip地址了。原因是 不知道什么時候 將 虛擬網絡編輯器 中的值改動了 要選擇這個 自動 選項

多模態大語言模型arxiv論文略讀(九十)

Hybrid RAG-empowered Multi-modal LLM for Secure Data Management in Internet of Medical Things: A Diffusion-based Contract Approach ?? 論文標題&#xff1a;Hybrid RAG-empowered Multi-modal LLM for Secure Data Management in Internet of Medical Things: A Di…

電腦主板VGA長亮白燈

電腦主板VGA長亮白燈 起因解決方法注意事項&#xff1a; 起因 搬家沒有拆機整機在車上晃蕩導致顯卡松動接觸不良&#xff08;一般VGA長亮白燈都和顯卡有關&#xff0c;主要排查顯卡&#xff09; 解決方法 將顯卡拆下重新安裝即可 注意事項&#xff1a; 不可直接拔下顯卡&a…

【監控】pushgateway中間服務組件

Pushgateway 是 Prometheus 生態中的一個中間服務組件&#xff0c;以獨立工具形式存在&#xff0c;主要用于解決 Prometheus 無法直接獲取監控指標的場景&#xff0c;彌補其定時拉取&#xff08;pull&#xff09;模式的不足。 其用途如下&#xff1a; 突破網絡限制&#xff1…

打造AI智能旅行規劃器:基于LLM和Crew AI的Agent實踐

引言 今天來學習大佬開發的一個AI驅動的旅行規劃應用程序&#xff0c;它能夠自動處理旅行規劃的復雜性——尋jni找航班、預訂酒店以及優化行程。傳統上&#xff0c;這個過程需要手動搜索多個平臺&#xff0c;常常導致決策效率低下。 通過利用**代理型人工智能&#xff08;Age…

21. 自動化測試框架開發之Excel配置文件的測試用例改造

21. 自動化測試框架開發之Excel配置文件的測試用例改造 一、測試框架核心架構 1.1 組件依賴關系 # 核心庫依賴 import unittest # 單元測試框架 import paramunittest # 參數化測試擴展 from chap3.po import * # 頁面對象模型 from file_reader import E…

如何在電力系統中配置和管理SNTP時間同步?

在電力系統中配置和管理 SNTP 時間同步需結合行業標準&#xff08;如《DL/T 1100.1-2019》&#xff09;和分層架構特點&#xff0c;確保安全性、可靠性和精度適配。以下是具體操作指南&#xff0c;涵蓋架構設計、設備配置、安全管理、運維監控四大核心環節&#xff0c;并附典型…

MTK-關于HW WCN的知識講解

前言: 最近做項目過程中和硬件打交道比較多,現在關于整理下硬件的HW wcn的知識點 一 MTK常見的MT6631 Wi-Fi 2.4GHz 匹配調諧指南 ?拓撲結構選擇? 推薦采用并聯電容拓撲(?shunt cap topology?)代替并聯電感拓撲(?shunt inductor topology?),以減少潛在電路設計…

(1)課堂 1--5,這五節主要講解 mysql 的概念,定義,下載安裝與卸載

&#xff08;1&#xff09;謝謝老師&#xff1a; &#xff08;2&#xff09;安裝 mysql &#xff1a; &#xff08;3&#xff09;鏡像下載 &#xff0c;這個網址很好 &#xff1a; &#xff08;4&#xff09; 另一個虛擬機的是 zhang 123456 &#xff1a; 接著配置…

U-Boot ARMv8 平臺異常處理機制解析

入口點&#xff1a;arch/arm/cpu/armv8/start.S 1. 判斷是否定義了鉤子&#xff0c;如有則執行&#xff0c;否則往下走。執行save_boot_params&#xff0c;本質就是保存一些寄存器的值。 2. 對齊修復位置無關碼的偏移 假設U-Boot鏈接時基址為0x10000&#xff0c;但實際加載到0…

mysql安裝教程--筆記

一、Windows 系統安裝 方法1&#xff1a;使用 MySQL Installer&#xff08;推薦&#xff09; 1. 下載安裝包 訪問 MySQL 官網下載頁面&#xff0c;選擇 MySQL Installer for Windows。 2. 運行安裝程序 雙擊下載的 .msi 文件&#xff0c;選擇安裝類型&#xff1a; ? Developer…

投資策略規劃最優決策分析

目錄 一、投資策略規劃問題詳細 二、存在最優投資策略&#xff1a;每年都將所有錢投入到單一投資產品中 &#xff08;一&#xff09;狀態轉移方程 &#xff08;二&#xff09;初始條件與最優策略 &#xff08;三&#xff09;證明最優策略總是將所有錢投入到單一投資產品中…

NGINX HTTP/3 實驗指南安裝、配置與調優

一、HTTP/3 簡介 基于 QUIC&#xff1a;在 UDP 之上實現的多路復用傳輸&#xff0c;內置擁塞控制與前向糾錯&#xff0c;無需三次握手即可恢復連接。零 RTT 重連&#xff1a;借助 TLS 1.3&#xff0c;實現連接恢復時的 0-RTT 數據發送&#xff08;視底層庫支持&#xff09;。多…