Vue 3 customRef 完全指南:自定義響應式引用的終極教程

📖 概述

customRef()?是 Vue 3 中用于創建自定義響應式引用的組合式 API。它允許開發者完全控制響應式數據的讀取和寫入行為,為復雜的響應式邏輯提供了強大的靈活性。

🎯 基本概念

什么是 customRef?

customRef()?是一個工廠函數,它接受一個工廠函數作為參數,返回一個自定義的響應式引用。通過自定義?get?和?set?函數,可以實現復雜的響應式邏輯。

核心特性

特性描述
完全控制自定義 getter 和 setter 邏輯
延遲計算支持懶加載和緩存機制
副作用處理精確控制依賴收集和觸發更新
類型安全完整的 TypeScript 支持

🔧 函數簽名

function customRef<T>(factory: (track: () => void,trigger: () => void) => {get: () => T;set: (value: T) => void;}
): Ref<T>;

📋 參數說明

參數類型描述
track() => void依賴收集函數,在 getter 中調用
trigger() => void觸發更新函數,在 setter 中調用

🎯 使用場景

1?? 防抖輸入框

創建帶有防抖功能的輸入框,避免頻繁觸發更新。

2?? 異步數據加載

實現懶加載和緩存機制的響應式數據。

3?? 數據驗證和轉換

在數據寫入時進行驗證和格式轉換。

💻 代碼示例

🚀 基礎用法

import { customRef } from "vue";// 創建一個簡單的自定義 ref
const count = customRef((track, trigger) => {let value = 0;return {get() {track(); // 收集依賴return value;},set(newValue) {value = newValue;trigger(); // 觸發更新},};
});// 使用
console.log(count.value); // 0
count.value = 10;
console.log(count.value); // 10

?? 防抖輸入框

import { customRef } from "vue";function useDebouncedRef(initialValue, delay = 300) {return customRef((track, trigger) => {let value = initialValue;let timeoutId = null;return {get() {track();return value;},set(newValue) {clearTimeout(timeoutId);timeoutId = setTimeout(() => {value = newValue;trigger();}, delay);},};});
}// 在組件中使用
const searchQuery = useDebouncedRef("", 500);

🔄 異步數據加載

import { customRef } from "vue";function useAsyncRef(fetcher) {return customRef((track, trigger) => {let value = null;let loading = false;let error = null;const load = async () => {if (loading) return;loading = true;error = null;trigger();try {value = await fetcher();} catch (err) {error = err;} finally {loading = false;trigger();}};return {get() {track();if (value === null && !loading) {load();}return { value, loading, error };},set(newValue) {value = newValue;trigger();},};});
}// 使用示例
const userData = useAsyncRef(() =>fetch("/api/user").then((res) => res.json())
);

? 數據驗證

import { customRef } from "vue";function useValidatedRef(initialValue, validator) {return customRef((track, trigger) => {let value = initialValue;let error = null;return {get() {track();return { value, error };},set(newValue) {try {const validationResult = validator(newValue);if (validationResult === true) {value = newValue;error = null;} else {error = validationResult;}} catch (err) {error = err.message;}trigger();},};});
}// 使用示例
const age = useValidatedRef(18, (value) => {if (value < 0) return "年齡不能為負數";if (value > 150) return "年齡不能超過150歲";return true;
});

🎨 在模板中使用

<template><div><!-- 防抖輸入框 --><input v-model="searchQuery" placeholder="搜索..." /><p>搜索內容: {{ searchQuery }}</p><!-- 異步數據 --><div v-if="userData.loading">加載中...</div><div v-else-if="userData.error">錯誤: {{ userData.error }}</div><div v-else>{{ userData.value }}</div><!-- 數據驗證 --><input v-model="age.value" type="number" /><p v-if="age.error" style="color: red;">{{ age.error }}</p></div>
</template><script setup>
import { useDebouncedRef, useAsyncRef, useValidatedRef } from "./composables";const searchQuery = useDebouncedRef("", 500);
const userData = useAsyncRef(() =>fetch("/api/user").then((res) => res.json())
);
const age = useValidatedRef(18, (value) => {if (value < 0) return "年齡不能為負數";return true;
});
</script>

?? 注意事項

🔢 依賴收集和觸發

  • ? 在?get()?函數中必須調用?track()
  • ? 在?set()?函數中必須調用?trigger()
  • ? 忘記調用會導致響應式失效

🕐 異步操作

  • ?? 在?set()?中進行異步操作時要小心
  • 🔄 考慮使用?nextTick()?確保 DOM 更新

🧹 內存泄漏

  • 🗑? 及時清理定時器和事件監聽器
  • 🔄 在組件卸載時清理資源

🎯 最佳實踐

1?? 封裝為組合式函數

將復雜的 customRef 邏輯封裝為可復用的組合式函數。

2?? 提供合理的默認值

為 customRef 提供合理的初始值,避免 undefined 狀態。

3?? 錯誤處理

在異步操作和驗證邏輯中添加適當的錯誤處理。

4?? 性能優化

避免在 getter 中進行昂貴的計算,考慮使用緩存機制。

? 常見問題

Q: customRef 和 computed 有什么區別?

A: customRef 提供完全的控制權,而 computed 是基于依賴的派生值。customRef 適合需要自定義 get/set 邏輯的場景。

Q: 可以在 customRef 中使用其他響應式數據嗎?

A: 可以,但需要確保正確調用 track() 來收集依賴。

Q: customRef 是否支持深層響應式?

A: 默認不支持,需要手動處理嵌套對象的響應式。

📝 總結

customRef()?是 Vue 3 中實現復雜響應式邏輯的強大工具。它提供了完全的控制權,適用于防抖、本地存儲同步、異步數據加載等場景。通過合理使用?track()?和?trigger()?函數,可以創建高效且靈活的響應式數據。在開發中,建議將復雜的 customRef 邏輯封裝為組合式函數,以提高代碼的可復用性和可維護性。

?Vue 3 customRef 完全指南:自定義響應式引用的終極教程 - 高質量源碼分享平臺-免費下載各類網站源碼與模板及前沿技術分享

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

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

相關文章

Java項目-蒼穹外賣_Day1

項目來源&#xff1a; 【黑馬程序員 Java項目實戰《蒼穹外賣》】 [https://www.bilibili.com/video/BV1TP411v7v6] ZZHow(ZZHow1024) 軟件開發整體介紹 軟件開發流程 需求分析&#xff1a;需求規格說明書、產品原型。設計&#xff1a;UI 設計、數據庫設計、接口設計。編碼…

面試可能問到的問題思考-MySQL

MySQL 1. 數據庫與緩存的一致性 引入緩存&#xff0c;因為緩存只是數據庫數據的副本&#xff0c;那么就可能存在副本和原數據不一致的情況 一致性 ACID里面的C&#xff0c;和CAP中的C不是一個概念&#xff0c;雖然都叫一致性。CAP中的C&#xff0c;指的是多個副本之間邏輯上…

【Java】 Spring Security 賦能 OAuth 2.0:構建安全高效的現代認證體系

還在為高昂的AI開發成本發愁?這本書教你如何在個人電腦上引爆DeepSeek的澎湃算力! 在當今數字化時代,認證與授權已成為應用系統安全的核心。OAuth 2.0 作為一種開放標準協議,廣泛應用于第三方授權場景中,而 Spring Security 則提供了強大的框架支持來實現這一協議。本文深…

實際工作幾月后常用相關命令筆記記錄

目前&#xff0c;我這只工程師幼崽經歷幾個月的工作&#xff0c;不能說是收獲很多&#xff0c;也算是成長經驗1吧。主要工作后才知道好多東西都是自己不會的不了解的&#xff0c;但是工作需要不一定自己完全吃透&#xff0c;在合適的地方正確的使用一般情況就ok了&#xff0c;所…

突破傳統文本切片的瓶頸:AntSK-FileChunk語義切片技術詳解前言:為什么我們需要重新思考文本切片?

在當今大語言模型&#xff08;LLM&#xff09;應用蓬勃發展的時代&#xff0c;我們面臨著一個看似簡單卻至關重要的問題&#xff1a;如何有效地處理長文本&#xff1f;無論是構建知識庫、實現RAG&#xff08;檢索增強生成&#xff09;系統&#xff0c;還是進行文檔智能分析&…

LeetCode-542. 01 矩陣

1、題目描述給定一個由 0 和 1 組成的矩陣 mat &#xff0c;請輸出一個大小相同的矩陣&#xff0c;其中每一個格子是 mat 中對應位置元素到最近的 0 的距離。兩個相鄰元素間的距離為 1 。示例 1&#xff1a;輸入&#xff1a;mat [[0,0,0],[0,1,0],[0,0,0]] 輸出&#xff1a;[[…

Elasticsearch如何確保數據一致性?

Elasticsearch 通過多種機制確保數據在分布式環境中的一致性&#xff0c;但由于其分布式和近實時&#xff08;Near Real-Time, NRT&#xff09;的特性&#xff0c;它提供的是最終一致性&#xff08;Eventual Consistency&#xff09;&#xff0c;而非強一致性。以下是核心機制和…

2026畢設選題-大數據-基于 Spring Boot的化妝品推薦系統的設計與實現

技術范圍&#xff1a;大數據、物聯網、SpringBoot、Vue、SSM、HLMT、小程序、PHP、Nodejs、Python、爬蟲、數據可視化、安卓App、機器學習等設計與開發。 主要內容&#xff1a;功能設計、開題報告、任務書、中期檢查PPT、系統功能實現、代碼編寫、論文編寫和輔導、論文降重、長…

數據結構算法:順序表

數據結構&#xff1a;順序表一.寄包柜1.題目如何創建數組&#xff1f;1. 需求本質2. 傳統靜態數組的缺陷3. 動態方案&#xff1a;向量的數組4. 核心邏輯5. 關鍵優勢總結2.解題思路2.1題目分析2.2具體解題邏輯拆解步驟2.3總結2.4參考代碼二.移動零1.題目2.解題思路2.1**解題核心…

IIS 安裝了.netcore運行時 還是報錯 HTTP 錯誤 500.19

IIS 安裝了.netcore運行時 還是報錯 HTTP 錯誤 500.19 - Internal Server Error 錯誤代碼 0x8007000d 我甚至是先安裝的SDK&#xff0c;再安裝的運行時runtime的安裝包&#xff0c;都不行。 而且在IIS的模塊中&#xff0c;找不到 AspNetCoreModuleV2。 最后在微軟官網n…

Flink 滑動窗口實戰:從 KeyedProcessFunction 到 AggregateFunction WindowFunction 的完整旅程

一、業務背景 我們要在 Flink 實時流上統計 每個用戶-品牌組合最近 1 小時的最晚行為時間&#xff0c;并且每 5 分鐘更新一次結果。 數據來自 Kafka&#xff0c;事件類型為 CartEvent&#xff1a; public class CartEvent {public String userId;public String brandId;public …

Kubernetes“城市規劃”指南:告別資源擁堵與預算超支,打造高效云原生都市

導讀&#xff1a; 如果把你的Kubernetes集群想象成一座拔地而起的現代化大都市&#xff0c;那么你&#xff0c;平臺工程師&#xff0c;就是這座城市的首席規劃師。然而&#xff0c;為何我們精心打造的許多“云原生都市”正迅速陷入交通擁堵、資源閑置和預算超支的困境&#xff…

2.4 Flink運行時架構:Task、SubTask、ExecutionGraph的關系

在理解Flink運行時架構之前&#xff0c;我們先用一個生活化的比喻來建立直觀認識&#xff1a; 想象你是一家大型工廠的總經理&#xff0c;需要生產一批復雜的產品。你會怎么做&#xff1f; 制定生產計劃&#xff1a;首先畫出生產流程圖&#xff0c;明確每個環節的工作內容分解任…

`mysql_query()` 數據庫查詢函數

1) 函數的概念與用途 mysql_query() 是 MySQL C API 中的核心函數&#xff0c;用于向 MySQL 服務器發送 SQL 查詢語句。這個函數充當了 C/C 應用程序與 MySQL 數據庫之間的橋梁&#xff0c;允許程序執行各種數據庫操作。 可以將 mysql_query() 想象成一個"數據庫信使"…

[系統架構設計師]通信系統架構設計理論與實踐(十七)

[系統架構設計師]通信系統架構設計理論與實踐&#xff08;十七&#xff09; 一.通信系統網絡架構 形式: 局域網&#xff0c;廣域網&#xff0c;移動通信網 1.局域網網絡架構 單一機構專用計算機的網絡 組成&#xff1a;計算機&#xff0c;交換機&#xff0c;路由器 特點&#x…

【趙渝強老師】Docker的私有鏡像倉庫:Harbor

Harbor是由VMware公司開發并開源的企業級的Docker鏡像倉庫的管理項目&#xff0c;它包括鏡像的權限管理&#xff08;RBAC&#xff09;、目錄訪問&#xff08;LDAP&#xff09;、日志審核、管理界面、自我注冊、鏡像復制和中文支持等功能。 視頻講解如下 【趙渝強老師】Docker的…

【QT/C++】實例理解類間的六大關系之泛化關系(Generalization)

【QT/C】實例理解類間的六大關系之泛化關系&#xff08;Generalization&#xff09; 在前面章節一文完美概括UML類圖及其符號&#xff08;超詳細介紹&#xff09;中已經對泛化關系的概念進行了總結&#xff0c;本文我將用實際案例來進一步理解泛化關系&#xff0c;以便應對未來…

【微服務的數據一致性分發問題】究極解決方案

文章目錄一、微服務數據分發1、簡介2、典型場景&#xff08;1&#xff09;跨服務業務流程協同&#xff08;2&#xff09;數據副本同步&#xff08;讀寫分離&#xff09;&#xff08;3&#xff09;實時狀態通知&#xff08;4&#xff09;數據聚合與統計分析&#xff08;5&#x…

挖幣與區塊鏈技術有怎樣的聯系?

挖幣&#xff08;通常指加密貨幣挖礦&#xff09;與區塊鏈技術有著緊密的聯系&#xff0c;挖礦是區塊鏈網絡維持運行和安全的重要機制之一&#xff0c;具體聯系如下&#xff1a;1. 挖礦是區塊鏈共識機制的核心環節區塊鏈通過“共識機制”確保全網節點對交易記錄達成一致&#x…

C數據結構:二叉樹(下)

C數據結構&#xff1a;二叉樹&#xff08;下&#xff09; 1.二叉樹遞歸結構遍歷 2.例題 3.二叉樹的性質 1.二叉樹遞歸結構遍歷 我們先創建一個如下圖所示的二叉樹。typedef int BTDataType; typedef struct BinaryTreeNode {BTDataType data;struct BinaryTreeNode* left;struc…