Vue3,用組合編寫更好的程式碼:靈活的引數(2/5)

前端小智發表於2022-07-06

有夢想,有乾貨,微信搜尋 【大遷世界】 關注這個在凌晨還在刷碗的刷碗智。

本文 GitHub https://github.com/qq449245884/xiaozhi 已收錄,有一線大廠面試完整考點、資料以及我的系列文章。

這是《用組合編寫更好的程式碼》第二篇,之前文章:

正文開始。

在使用 vue 組合時,有時候想用 ref,有時候又不想使用。本節,介紹一種模式,可以讓我即可以使用 ref,又可以不使用,從而讓元件更具有靈活性。

使用ref和unref獲得更靈活的引數

幾乎所有可組合物件都需要某種型別的引數作為輸入。通常,這是一個響應式 ref。它也可以是一個原始的Javascript型別,比如字串、數字或物件。

但是我們想要編寫更加靈活和可重用的組合,所以我們不僅要接收 ref 型別的引數也可以接收原始型別引數,然後我們將引數轉換為我們需要引數。如下所示:

// 傳遞一個 ref
const countRef = ref(2);
useCount(countRef);

// 或者直接一個數字
const countRef = useRef(2);

VueUse 中的 useTitle 也是採用這種模式。

當我們傳入一個 ref 時,網頁標題就可以通過 .value 的方式來動態更改。

const title = ref('This is the title');
useTitle(title);
title.value = 'New title please';

如果傳入的是一個字串,useTitle內部會建立一個 ref,值為我們所傳入的字元,最後返回一個 ref 變數,然後 .value 的方式來動態更改。

const title = useTitle('This is the title');
title.value = 'New title please';

在組合中實現一個靈活的引數

為了讓靈活的引數模式能工作,我們需要對得到的引數使用ref函式或unref函式。

export default useMyComposable(input) {
  const ref = ref(input);
}

export default useMyComposable(input) {
  const rawValue = unref(input);
}

ref 函式將為我們建立一個新的ref。但如果我們傳給它一個ref,它只是把這個ref返回給我們

// 建立一個 ref
const myRef = ref(0);

// 結果是相等的
assert(myRef === ref(myRef));

unref函式的工作原理是一樣的,但是它要麼解開一個ref,要麼把我們的原始值還給我們。

const value = unref(myRef);

// 結果是相等的
assert(value === unref(value));

讓我們看看VueUse中的一些組合是如何實現這個模式的。VueUse是Vue 3的一個開源組合集合,編寫得非常好。它是學習如何編寫可組合程式碼的一個很好的資源

useTitle

回到useTitle,這個我們已經很熟悉它。

這種可組合的模式可以讓我們傳入一個字串或一個字串的 ref。它並不關心我們提供的是哪一個。

// Pass in a string
const titleRef = useTitle('Initial title');

// Pass in a ref of a string
const titleRef = ref('Initial title');
useTitle(titleRef);

在原始碼中,可以看到,在我們對選項物件進行解構之後,我們就建立了title ref。這裡使用了ref函式,它允許我們使用一個ref或一個字串來建立 title 的 ref。

// ...
const title = ref(newTitle ?? document?.title ?? null)
// ...

這裡的意思是先取 newTitle 作為初始化值,如果沒有在取 document?.title,還是沒有就取 null

對於TypeScript 使用者來說,這裡有一些趣事需要注意。

這裡使用的newTitle變數的型別是MaybeRef<string>。下面是這個型別的定義:

type MaybeRef<T> = T | Ref<T>

這個型別定義意味著 MaybeRef<string> 型別既可以是一個字串,也可以是一個Ref<string>,也就是一個裡面有一個字串值的Ref

我們接著看下一個組合也是使用這種型別來實現這種模式。

useCssVar

useCssVar 組合允許我們抓取一個CSS變數的值並在我們的應用程式中使用它。

const backgroundColor = useCssVar('--background-color');

但與useTitle不同的是,這裡我們需要字串值,這樣我們就可以在DOM中查詢CSS變數。使用unref函式,這個可組合的函式可以同時處理傳入的引用和字串。

// Using a string
const backgroundColor = useCssVar('--background-color');

// Using a ref
const cssVarRef = ref('--background-color');
const backgroundColor = useCssVar(cssVarRef);

看一下原始碼,我們可以看到它使用unref函式來完成這個任務。實際上,它使用了一個輔助函式,叫做unrefElement,以確保我們得到的是一個DOM元素,而不只是一個Vue例項。

如果想進一步探索它,VueUse中的大多陣列合都實現了這種模式。所以,選擇一個感興趣的,然後深入到程式碼中去吧。

總結

我們剛剛花了一些時間學習了這個系列的第二個模式,在這個模式中,我們可以通過在我們的可組合程式中巧妙地使用 refunref 來更靈活地使用引數。無論你碰巧有一個ref還是隻有Javascript的原始值,可合成的東西仍然可以工作。它能適應你的使用方式!

我們還看了VueUse庫如何在 useTitleuseCssVar 組合中實現這種模式。useTitle 組合使用 ref 函式,而 useCssVar 使用 unref 函式,這樣我們就可以看到兩種變化的作用。

在下一篇文章中,我們將介紹另一種模式,通過使返回值動態化來改進它們。我們將學習如何根據需要,返回一個單一的值或一個物件。

// Returns a single value
const isDark = useDark();

// Returns an object of values
const {
  counter,
  pause,
  resume,
} = useInterval(1000, { controls: true });

這種模式可以使你的可組合性在使用上簡單得多,特別是當你在大多數時候只需要一個單一的值時。

編輯中可能存在的bug沒法實時知道,事後為了解決這些bug,花了大量的時間進行log 除錯,這邊順便給大家推薦一個好用的BUG監控工具 Fundebug

作者:Michael Thiessen 譯者:小智 來源:vuemastery

原文: https://www.vuemastery.com/bl...

交流

有夢想,有乾貨,微信搜尋 【大遷世界】 關注這個在凌晨還在刷碗的刷碗智。

本文 GitHub https://github.com/qq449245884/xiaozhi 已收錄,有一線大廠面試完整考點、資料以及我的系列文章。

相關文章