Hooks是什么?為啥Vue和React都選擇了它?
Hooks是什么
"hooks" 直譯是 “鉤子”,它并不僅是 react,甚至不僅是前端界的專用術語,而是整個行業所熟知的用語。通常指:系統運行到某一時期時,會調用被注冊到該時機的回調函數。
為啥要用Hooks
- 跨組件復用stateful logic十分困難 使用Hooks,你可以在將含有state的邏輯從組件中抽象出來,這將可以讓這些邏輯容易被測試。同時,Hooks可以幫助你在不重寫組件結構的情況下復用這些邏輯。
- 復雜的組件難以理解 Hooks允許您根據相關部分(例如設置訂閱或獲取數據)將一個組件分割成更小的函數,而不是強制基于生命周期方法進行分割。
- 不止是用戶,機器也對Classes難以理解 Hooks讓你可以在classes之外使用更多React的新特性。
Hooks的優點
更好的狀態復用
假設有如下需求:
當組件實例創建時,需要創建一個 state 屬性:name,并隨機給此 name 屬性賦值一個初始值。除此之外,還得提供一個 setName 方法。你可以在組件其他地方開銷和修改此狀態屬性。
更重要的是: 這個邏輯要可以復用,在各種業務組件里復用這個邏輯。
在擁有 Hooks 之前,我首先會想到的解決方案一定是 mixin。
代碼如下:(此示例采用 vue2 mixin 寫法 )。
// 混入文件:name-mixin.js
export default {
data() {
return {
name: genRandomName() // 假如它能生成隨機的名字
}
},
methods: {
setName(name) {
this.name = name
}
}
}
// 組件:my-component.vue
<template>
<div>{{ name }}</div>
<template>
<script>
import nameMixin from './name-mixin';
export default {
mixins: [nameMixin],
// 通過mixins, 你可以直接獲得 nameMixin 中所定義的狀態、方法、生命周期中的事件等
mounted() {
setTimeout(() => {
this.setName('Tom')
}, 3000)
}
}
<script>
雖然看起來好像是可以復用的,但是React官方出來說話了。
既然被斃了,肯定是有它的原因的,雖然是可以實現復用,但是顯露的弊端也是非常的明顯的。
方法和屬性難以監聽
export default {
mixins: [ a, b, c, d, e, f, g ], // 當然,這只是表示它混入了很多能力
mounted() {
console.log(this.name)
// mmp!這個 this.name 來自于誰?我難道要一個個混入看實現?
}
}
屬性、方法會覆蓋
當我同時想混入 mixin-a.js 和 mixin-b.js 以同時獲得它們的屬性或者方法的時候,比較尷尬的事情發生了:由于這兩個 mixin 功能的開發者心有靈犀,它們都定義了 this.name 作為屬性。這種時候,這個時候的你就會傻傻分不清。
代碼結構
這就是為啥Vue3尤大大使用CompostionAPI的原因了。
這樣帶來的好處是顯而易見的:“高度聚合,可閱讀性提升”。伴隨而來的便是 “效率提升,bug變少”。
趨勢
2019年年初,react 在 16.8.x 版本正式具備了 hooks 能力。2019年6月,尤雨溪在 vue/github-issues 里提出了關于 vue3 Component API 的提案。(vue hooks的基礎)在后續的 react 和 vue3 相關版本中,相關 hooks 能力都開始被更多人所接受。除此之外,solid.js、 preact 等框架,也是開始選擇加入 hooks 大家庭。