目录
[1. 何为Hooks](#1. 何为Hooks)
[2. 使用场景](#2. 使用场景)
[3. 常见的 Hooks 函数](#3. 常见的 Hooks 函数)
[4. 实例](#4. 实例)
[4.1简易hook 例子](#4.1简易hook 例子)
[4.2 自定义scrolltop例子](#4.2 自定义scrolltop例子)
[4.3 mousemoveHandler例子](#4.3 mousemoveHandler例子)
[4.4 useCountDown例子](#4.4 useCountDown例子)
1. 何为Hooks
Hooks 是一种函数,用于封装组件中的逻辑。它可以包含状态、计算属性、生命周期钩子等,并且可以在多个组件之间共享和复用。
2. 使用场景
-
逻辑复用:通过 Hooks,可以将一组相关的逻辑封装在一个函数中,提高代码的可复用性。
-
代码组织:使得组件逻辑更加清晰,避免大型组件选项过于臃肿。
-
提高可读性和维护性:将相关逻辑分离成多个小函数,使得每个函数的职责更加清晰,便于理 解和维护。
3. 常见的 Hooks 函数
-
reactive、ref、computed:用于创建响应式数据。
-
watch、watchEffect:用于监听数据变化。
-
onMounted、onUpdated、onUnmounted:用于处理组件的生命周期。
-
自定义 Hooks:根据业务逻辑封装的自定义函数,例如下述提到的 useCountDown。
4. 实例
4.1简易hook 例子
javascript
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
javascript
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-y
const 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+=frameOffset
else{
//这部分让平滑动画,直接赋值
target.scrollTop=y
clearInterval(timer)
timer=null
}
},40)
}
}
//响应式数据实时滚动距离
const scrollTop=ref(0)
const scrollHandler=(e)=>{
//同步scrolltop
scrollTop.value = target.scrollTop
}
//组件挂载时候添加scrollhandler
onMounted(()=>{
target.addEventListener("scroll",scrollHandler)
})
//组件卸载时候移除scrollhandler
onUnmounted(()=>{
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例子
javascript
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例子
javascript
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