本篇文章為大家帶來了關於Hooks與vue的相關知識,Hooks是React在V16.7.0-alpha版本中引入的,Hooks主要是對模式的複用提供了一種更明確的思路,希望對大家有幫助。
不要把Hooks 和Vue 的生命週期鉤子(Lifecycle Hooks) 弄混了,Hooks 是React 在V16.7.0-alpha 版本中引入的,而且幾天后Vue 發布了其概念驗證版本。雖然 Hooks 是由 React 提出的,它是一個對各 JavaScript 框架生態系統都有價值的、重要的組合機制,因此我們今天會花一點時間討論 Hooks 意味著什麼。
Hooks主要是對模式的複用提供了更明確的思路 —— 避免重寫元件本身,並允許有狀態邏輯的不同部分能無縫地進行協同工作。
就 React 而言,問題在於:在表達狀態的概念時,類別是最常見的元件形式。無狀態函數式元件也非常受歡迎,但由於它們只能單純地渲染,所以它們的用途僅限於展示任務。
類別本身存在一些問題。例如,隨著 React 變得越來越流行,類別的問題也普遍成為新手的阻礙。開發者為了理解 React,也必須理解類別。綁定使得程式碼冗長且可讀性差,並且需要理解 JavaScript 中的 this
。這裡也討論了使用類別所帶來的一些最佳化障礙。
在邏輯重複使用方面,我們通常使用 render props 和高階元件等模式。但使用這些模式後會發現自己處於類似的「厄運金字塔」中 —— 樣式實現地獄,即過度使用嵌套可能會導致組件難以維護。這導致我想對 Dan Abramov 像喝醉了一樣大吼大叫,沒有人想要那樣。
Hooks 讓我們可以使用函數呼叫來定義元件的有狀態邏輯,從而解決這些問題。這些函數呼叫變得更具組合性、可重複使用性,並且允許我們在使用函數式元件的同時能夠存取和維護狀態。 React 發布Hooks 時,人們很興奮—— 下面你可以看到Hooks 展示的一些優勢,關於它們如何減少程式碼和重複:
在維護方面,簡單性是關鍵,Hooks 提供了一種單一的、函數式的方式來實現邏輯共享,並且可能程式碼量更小。
讀到這裡你一定想知道 Hooks 在 Vue 中必須提供什麼。這似乎是一個不需要解決的問題。畢竟,類別並不是 Vue 主要使用的模式。 Vue 提供無狀態函數式元件(如果需要它們),但為什麼我們需要在函數式元件中攜帶狀態?我們有 mixins 用於組合可以在多個元件中重複使用的相同邏輯。問題解決了。
我想到了同樣的事情,但在與 Evan You 交談後,他指出了我忽略的一個主要用例:mixins 不能相互消費和使用狀態,但 Hooks 可以。這意味著如果我們需要鍊式封裝邏輯,可以使用 Hooks。
Hooks 實作了 mixins 的功能,但避免了 mixins 帶來的兩個主要問題:
如果使用多個 mixins,我們不清楚哪個屬性是由哪個 mixins 提供的。使用 Hooks,函數的回傳值會記錄消費的值。
那麼,這在 Vue 中如何運作呢?我們之前提到過,在使用 Hooks 時,邏輯在函數呼叫時表達從而可重複使用。在 Vue 中,這意味著我們可以將資料呼叫、方法呼叫或計算屬性呼叫封裝到另一個自訂函數中,並使它們可以自由組合。資料、方法和計算屬性現在可用於函數式元件了。
讓我們來看一個非常簡單的 hook,以便我們在繼續學習 Hooks 中的組合範例之前理解建構塊。
好的,Vue Hooks 和 React Hooks 之間存在交叉部分。使用 use
作為前綴是 React 的約定,所以如果你在 React 中尋找 Hooks,你會發現 Hooks 的名稱都會像 useState
、useEffect
等。更多資訊可以查看這裡。
在 Evan 的線上 demo 裡,你可以看到他在何處訪問 useState
和 useEffect
並用於 render 函數。
如果你不熟悉 Vue 中的 render 函數,那麼看官網文件可能會有所幫助。
但當我們使用 Vue 風格的 Hooks 時,我們會如何命名呢 —— 你猜對了 —— 例如:useData
,useComputed
等等。
因此,為了讓我們看看如何在 Vue 中使用 Hooks,我創建了一個範例應用程式供我們探索。
在 src/hooks 資料夾中,我創建了一個 hook,它在 useMounted
hook 上阻止了滾動,並在 useDestroyed
上重新啟用滾動。這有助於我在打開查看內容的對話框時暫停頁面滾動,並在查看對話框結束時再次允許滾動。這是一個好的抽像功能,因為它在整個應用程式中可能會多次使用。
import { useDestroyed, useMounted } from "vue-hooks";export function preventscroll() { const preventDefault = (e) => { e = e || window.event; if (e.preventDefault) e.preventDefault(); e.returnValue = false; } // keycodes for left, up, right, down const keys = { 37: 1, 38: 1, 39: 1, 40: 1 }; const preventDefaultForScrollKeys = (e) => { if (keys[e.keyCode]) { preventDefault(e); return false; } } useMounted(() => { if (window.addEventListener) // older FF window.addEventListener('DOMMouseScroll', preventDefault, false); window.onwheel = preventDefault; // modern standard window.onmousewheel = document.onmousewheel = preventDefault; // older browsers, IE window.touchmove = preventDefault; // mobile window.touchstart = preventDefault; // mobile document.onkeydown = preventDefaultForScrollKeys; }); useDestroyed(() => { if (window.removeEventListener) window.removeEventListener('DOMMouseScroll', preventDefault, false); //firefox window.addEventListener('DOMMouseScroll', (e) => { e.stopPropagation(); }, true); window.onmousewheel = document.onmousewheel = null; window.onwheel = null; window.touchmove = null; window.touchstart = null; document.onkeydown = null; }); }
然後我們可以在像AppDetails.vue 一樣的Vue 元件中呼叫它:
<script> import { preventscroll } from "./../hooks/preventscroll.js"; ...export default { ... hooks() { preventscroll(); } } </script>
我們不僅可以在該元件中使用它,還可以在整個應用程式中使用相同的功能!
我們之前提到過,Hooks 和 mixins 之間的主要區別之一是 Hooks 實際上可以互相傳值。讓我們來看看這個簡單但有點不自然的例子。
在我們的應用程式中,我們需要在一個可重複使用的 hook 中進行計算,還有一些需要使用該計算結果的東西。在我們的例子中,我們有一個 hook,它獲取視窗寬度並將其傳遞給動畫,讓它知道只有當我們在更大的螢幕上時才會觸發。
詳見影片示範:css-tricks.com/wp-content/…
第一個hook:
import { useData, useMounted } from 'vue-hooks';export function windowwidth() { const data = useData({ width: 0 }) useMounted(() => { data.width = window.innerWidth }) // this is something we can consume with the other hook return { data } }
然後,在第二個hook 中,我們使用它來創建一個觸發動畫邏輯的條件:
// the data comes from the other hookexport function logolettering(data) { useMounted(function () { // this is the width that we stored in data from the previous hook if (data.data.width > 1200) { // we can use refs if they are called in the useMounted hook const logoname = this.$refs.logoname; Splitting({ target: logoname, by: "chars" }); TweenMax.staggerFromTo(".char", 5, { opacity: 0, transformOrigin: "50% 50% -30px", cycle: { color: ["red", "purple", "teal"], rotationY(i) { return i * 50 } } }, ...
然後,在元件內部,我們將一個hook 作為參數傳遞給另一個hook:
<script> import { logolettering } from "./../hooks/logolettering.js"; import { windowwidth } from "./../hooks/windowwidth.js";export default { hooks() { logolettering(windowwidth()); } }; </script>
現在我們可以在整個應用程式中使用Hooks 來寫邏輯!再提一下,這是一個用於演示目的不太自然的例子,但你可以看到這對於大型應用程序,將邏輯保存在較小的、可復用的函數中是有效的
【相關推薦:《vue.js教學》】
以上是一起聊聊Hooks對Vue而言意味著什麼的詳細內容。更多資訊請關注PHP中文網其他相關文章!