三個實例來自? ?learn_vue: 【教學工程】學習vue2/vue3 (gitee.com)
?
目錄
1. 何為Hooks
?2. 使用場景
? 3. 常見的 Hooks 函數
? 4. 實例
?4.1簡易hook 例子
?4.2 自定義scrolltop例子
?4.3?mousemoveHandler例子
?4.4?useCountDown例子
1. 何為Hooks
? ?Hooks 是一種函數,用于封裝組件中的邏輯。它可以包含狀態、計算屬性、生命周期鉤子等,并且可以在多個組件之間共享和復用。
?2. 使用場景
? ?- 邏輯復用:通過 Hooks,可以將一組相關的邏輯封裝在一個函數中,提高代碼的可復用性。
? ?- 代碼組織:使得組件邏輯更加清晰,避免大型組件選項過于臃腫。
? ?- 提高可讀性和維護性:將相關邏輯分離成多個小函數,使得每個函數的職責更加清晰,便于理? ? ? ?解和維護。
? 3. 常見的 Hooks 函數
? ?-? reactive、ref、computed:用于創建響應式數據。
? ?- watch、watchEffect:用于監聽數據變化。
? ?- onMounted、onUpdated、onUnmounted:用于處理組件的生命周期。
? ?-? 自定義 Hooks:根據業務邏輯封裝的自定義函數,例如下述提到的 useCountDown。
? 4. 實例
? ? ?4.1簡易hook 例子
import { ref } from 'vue';
export default function useCounter() {const count = ref(0);const increment = () => {count.value++;};return {count,increment,};
}
??下述,hooks不是一定要有state
? ? 4.2 自定義scrolltop例子
??注意 一般hooks里包括一些函數鉤子,比如mounted,注意 hooks里重要的是state一般被包裹在函數里面,這樣不同組件調用 不會共享state
export default function (target=window,dataRef = null){let timer=null//一鍵回到頂部 時間默認1000毫秒const toTop=(millis=1000)=>{yScrollTo(0,millis)}const yScrollTo=(y,millis=500)=>{if(!timer){const offset = target.scrollTop-yconst frameOffset = Math.abs(offset / (millis / 40));timer=setInterval(()=>{if(offset>0 && target.scrollTop-y >frameOffset){target.scrollTop-=frameOffset}else if(offset<0 && y-target.scrollTop>0)target.scrollTop+=frameOffsetelse{
//這部分讓平滑動畫,直接賦值target.scrollTop=yclearInterval(timer)timer=null}},40)}}//響應式數據實時滾動距離const scrollTop=ref(0)const scrollHandler=(e)=>{
//同步scrolltopscrollTop.value = target.scrollTop}//組件掛載時候添加scrollhandleronMounted(()=>{target.addEventListener("scroll",scrollHandler)})//組件卸載時候移除scrollhandleronUnmounted(()=>{
target.removeEventListener("scroll", scrollHandler)})onActivated(()=>{if(dataRef){//如果存在要恢復的數據yScrollTo(dataRef.value)console.log("滾動位置已恢復為",dataRef.value)}})onDeactivated(()=>{if(dataRef){console.log("離開時滾動的位置",scrollTop.value)dataRef.value = scrollTop.value}})return scrollTop
}
函數兩個參數,第一個參數 target=window,獲取目標要滾動到的位置,第二個參數dataRef 如果提供 代表要緩存離開時候 當前滾動到的位置 方便下次回來時候恢復到dataRef的位置
防止同時多次調用滾動動畫:
timer為空變送沒有正在進行的滾動動畫 可以啟動一個新的滾動動畫
4.3?mousemoveHandler例子
function useMouse(){
const state = reactive({
x:0,
y:0
})
const mousemoveHandler=(e)=>{
//更新實時數據
state.x = e.pageX
state.y = e.pageY
}
//組件掛載時候建立mousemove事件監聽器
onMounted(()=>{
window.addEventListener("mousemove",mousemoveHandler)
})
onUnmounted(()=>{
window.removeEventListener("mousemove",mousemoveHandler)
})
return toRefs(state)
//將state里的屬性拆開每個都是響應式數據}
export default mousemoveHandler
4.4?useCountDown例子
function getTimeDiffer(startDate, endDate){
let timeDiff = endDate-startDate
// 計算過去了多少天
var daysDiffer = parseInt(timeDiffer / (24 * 3600 * 1000));
// console.log(daysDiffer);// 計算不足一天的時分秒 odd奇數,零頭
var oddMillis = timeDiffer % (24 * 3600 * 1000);
var hoursDiffer = parseInt(oddMillis / (3600 * 1000));
// console.log(hoursDiffer);// 不足一小時的零頭毫秒
oddMillis = oddMillis % (3600 * 1000);
var minutesDiffer = parseInt(oddMillis / (60 * 1000));
// console.log(minutesDiffer);// 計算秒
var secondsDiffer = Math.round((oddMillis % (60 * 1000)) / 1000);
// console.log(secondsDiffer);
return {
daysDiffer,
hoursDiffer,
minutesDiffer,
secondsDiffer,
}}const useCountDown = (targetDate)=>{
//targetDate: new Date(2023, 0, 1),
const state = reactive({
days:0,
hours:0,
minutes:0,
seconds:0
})let timer = null
onMounted(()=>{
timer = setInterval(()=>{
const {daysDiffer,hoursDiffer,minutesDiffer,secondsDiffer}=getTimeDiffer(new Date(),targetDate)
state.days = daysDiffer;
state.hours = hoursDiffer;
state.minutes = minutesDiffer;
state.seconds = secondsDiffer;},1000)
})
/* 組件卸載時移除定時器 */
onUnmounted(() => {
if (timer) {
clearInterval(timer);
console.log(“timer已移除”);
}
});// {days,hours,minutes,seconds}
return toRefs(state);}
export default useCountDown