本文要談到的 Hooks,不同於 Lifecycle Hooks(生命週期勾點),它是在 v16.7.0-alpha 中引入 React 的;儘管 Hooks 是由 React 提出,但是它的本質是一種重要的程式碼組合機制,對於整個 JavaScript 的框架系統都大有好處;今天花點時間具體來談談:Hooks 對於 Vue 意義著什麼?
Hooks 提供了一種更明確的方式來組織程式碼,使得程式碼能重用,更重要的是,它允許不同的邏輯部分進行通訊、協同工作。【相關推薦:】
Hooks 為什麼被提出?就 React 而言,最初的問題背景是這樣的:
在表達狀態概念時,類 是最常見的組織形式。類本身存在一些問題,比如繫結關係冗長、複雜,導致不易讀,This 的指向總會讓人摸不清頭腦;
不僅如此,在重用方面,使用渲染工具或高階元件類的模式很常見,但這樣容易陷入 「pyramid of doom」 (末日金字塔),可以將它理解為過度的巢狀關係;
Hooks 就是來解決這些問題的;Hooks 允許我們使用函數呼叫來定義元件的狀態邏輯,這些函數有更強的組合性、重用性;同時,仍然可以進行狀態的存取和維護;
範例:@dan_abramov's code from #ReactConf2018
有圖①到圖②的轉變,對元件程式碼進行了再次組合,然後以函數的的方式進行匯出,供外部重用;
在維護方面,Hooks 提供了一種單一的、功能性的方式來處理共用邏輯,並有可能減少程式碼量。
那 Vue 中為什麼要用 Hooks 呢?畢竟 Vue 中沒有很頻繁的使用類;在 Vue 中我們使用 mixin 來解決元件相同的重用邏輯;
mixin 的問題在哪?Hooks 能解決嗎?
問題主要有兩點:
mixin 之間不能傳遞狀態;
邏輯來源並沒有清晰的說明;
而這兩點,Hooks 能很好地解決;
舉個例子:
Hooks1
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 } }
// the data comes from the other hook export 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 } } }, ...
兩個勾點之間傳值:
<script> import { logolettering } from "./../hooks/logolettering.js"; import { windowwidth } from "./../hooks/windowwidth.js"; export default { hooks() { logolettering(windowwidth()); } }; </script>
我們可以在整個應用程式中使用 Hooks 組合邏輯;
在 src/hooks 資料夾中,建立了一個 Hooks,用於實現:開啟對話方塊檢視內容時,暫停頁面,並在檢視完對話方塊後,允許再次捲動。
它很有可能在應用程式中被多次使用;
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 元件中呼叫它:
<script> import { preventscroll } from "./../hooks/preventscroll.js"; ... export default { ... hooks() { preventscroll(); } } </script>
Vue Hooks 已經可以與 Vue 2.x 一起使用,但仍處於試驗階段。我們計劃將 Hooks 整合到 Vue 3 中,但是它跟 React Hooks 還是會有所差異;
Hooks 已經應用到 Vue3 了,也就是 setup 那一坨,但是它確實有一些不同於 React 的 Hooks 的地方;推薦閱讀 Vue3 究竟好在哪裡?(和 React Hook 的詳細對比)
地址 https://zhuanlan.zhihu.com/p/133819602
其實理解到它的設計意圖了,即使不原原本本的挪用框架,自己用 JS 原生,也能整一個類似的複用邏輯吧。把實現一個完整功能的邏輯,封裝進一個函數中,就看函數名稱,就知道它是幹嘛的了,不用知道其內部實現,如果想知道,再到對應的 hooks 裡面去找,至少就這一點來說,和函數語言程式設計設計思路是一致的;
本篇主體譯自:what-hooks-mean-for-vue(https://css-tricks.com/what-hooks-mean-for-vue/)
作者:Sarah Drasner
更多程式設計相關知識,請存取:!!
以上就是深入瞭解Vue中的Hooks,聊聊它對於 Vue 的意義!的詳細內容,更多請關注TW511.COM其它相關文章!