vue3 自定义hook useSafeListener

海星吧 2022-3-20 6314

学过vue的同学应该知道,vue2在组件中使用定时器setInterval、window监听事件之类的时候是有副作用的。

然而在vue3的开发中,这样的问题其实很好解决,

接下来为大家介绍一下vue3开发中的自定义hooks。

src/hooks

src/hooks/useSafeListener.js

import { onMounted, onUnmounted, ref } from "vue";

export function useSafeHook(run,clear) {
	onMounted(() => {
		clear()
		run()
	});
	onUnmounted(() => {
		clear()
	});
}

//获得一个安全的定时器
export function useSafeInterval(fn, wait = 1000) {
	const timer = ref(null);
	function runTimer() {
		timer.value = setInterval(fn, wait)
	}
	function clearTimer() {
		clearInterval(timer.value)
	}
	useSafeHook(runTimer,clearTimer)
	return { runTimer, clearTimer };
}

//获得一个安全的window绑定事件
export function useSafeListener(eventType, fn, useCapture = false) {
	function add() {
		window.addEventListener(eventType, fn, useCapture);
		fn();
	}
	function remove() {
		window.removeEventListener(eventType, fn, useCapture);
	}
	useSafeHook(add,remove)
	return { add, remove };
}

在这个文件里我定义了三个函数,

useSafeHook(创建监听,关闭监听)
useSafeInterval(定时器的方法体,定时器计时时间)
useSafeListener(window监听事件名,监听触发的事件,是否在捕获时执行)

 

其中useSafeHook是复用且重要的函数,其另外两个都会用到。

得益于vue3的组合式api,可以复用生命周期函数。

他接受两个函数,第一个是需要创建的监听函数,第二个是关闭监听的函数

现在来看看它们的作用。

创建两个页面,homepage and page1

homepage 作为路由默认页面 '/'

useSafeHook =>
homepage=>
<template>
	<div class="homepage">
		this view is homepage =>
		<router-link to="/page1">to page1</router-link>
	</div>
</template>
<script setup>
import {
	ref
} from 'vue'
import {
	useSafeHook,
} from "@/hooks/useSafeListener"
const timer = ref(null);
function runTimer() {
	timer.value = setInterval(()=> {
		console.log('set timer')
	}, 1000)
}
function clearTimer() {
	clearInterval(timer.value)
        console.log(timer.value)
        console.log(timer)
}
useSafeHook(
	runTimer, clearTimer
)
</script>
<template>
	<div>
		this view is page1 =>
		<router-link to="/">to homepage</router-link>
	</div>
</template>

页面开始的时候会先清除然后再触发定时器,那么在离开这个界面会怎么样呢?

可以看到本应该是一个定时器函数的timer的value已经被改变了,当然它的值变成了32是因为porxy

的原因。

 这里已经实现了一个useSafeInterval,那么看看useSafeInterval是否也是如此。

<template>
	<div class="homepage">
		this view is homepage =>
		<router-link to="/page1">to page1</router-link>
	</div>
</template>
<script setup>
import {
	useSafeInterval,
} from "@/hooks/useSafeListener"
useSafeInterval(() => {
	console.log('set timer 1')
})
</script>

 

 由于无法制作gif,所以利用了一下桌面的时钟。

05 秒的时候定时器运行了4次

37秒之前我已经进入page1了,它运行了19次,也就是说我在17秒之前就已经进入了page1

那个时候,定时器已经被关闭了,看起来就是这样,它确实被关闭了。

那么最后一个window监听是否也是如此呢?

<template>
	<div class="homepage">
		this view is homepage =>
		<router-link to="/page1">to page1</router-link>
	</div>
</template>
<script setup>
import {
	useSafeListener,
} from "@/hooks/useSafeListener"
useSafeListener('resize',()=>{
	console.log('resize is change')
})
</script>

 这是初次进入的时候页面的大小,

当我把页面变宽之后,它同样的触发了一次。那么看看进入了其他的页面是否还是存在。

当我进入到page1的时候,它已经被销毁了,所以我更改页面大小他也不会触发函数,因为它已经被销毁了。

以上就是我写的自定义hooks,安全的监听 useSafeListener。

当然我在 useSafeInterval 和 useSafeListener上返回了他们的启动函数和销毁函数,

你可以使用const listener 等于他们其中的一个,并且使用listener. 函数名来提前销毁或再次创建。

这样更加灵活 ,并且它会在组件结束时被销毁,你无需担心副作用的诞生。

如果有需要就拿去用吧,或许你也有更好的想法可以联系我。

<template>
	<div class="homepage">
		this view is homepage =>
		<router-link to="/page1">to page1</router-link>
	</div>
</template>
<script setup>
import {
	ref
} from 'vue'
import {
	useSafeHook,
	useSafeInterval,
	useSafeListener,
} from "@/hooks/useSafeListener"
const timer = ref(null);
function runTimer() {
	timer.value = setInterval(()=> {
 		console.log('set timer')
	}, 1000)
 }
function clearTimer() {
 	clearInterval(timer.value)
	console.log(timer.value)
	console.log(timer)
 }
 useSafeHook(
 	runTimer, clearTimer
 )
 useSafeInterval(() => {
 	console.log('set timer 1')
 })
useSafeListener('resize',()=>{
	console.log('resize is change')
})

</script>

 这里是海星吧,我们下次见。

拜拜

弱鸡程序员年底还在加班
最新回复 (7)
  • 海星吧 2022-3-20
    1 2
    编辑器没有代码注释这么个东西就很操蛋
    弱鸡程序员年底还在加班
  • 海星吧 2022-3-20
    0 3
    推荐一个vue3的自定义hook库,vueuse,这个东西已经有了百来个hook了,有兴趣可以去学习学习,
    我上周看这个库花了一整个下午才看完。
    弱鸡程序员年底还在加班
  • 欧派兽 2022-3-20
    0 4
    奖励三级精华
    1:管理员给你移区后会显示移到了你之前发帖的区。 2:点击我作为楼主发帖时一楼下的图片签名,可以跳转到站规教程贴。 3:多次水贴水回复会封号哦? 4:不知道回什么的时候就点“里世界专属”,一键随机生成几种回复内容。 5:祝你在里世界玩得愉快!
  • 喀秋莎 2022-3-20
    0 5
    在?能不能写个自动下片的脚本?
    我在上班,别发骚图了。
  • 海星吧 2022-3-20
    0 6
    喀秋莎 在?能不能写个自动下片的脚本?
    我只会写一些工作时候用的东西。自动下片还是找找迅雷的工作室看看有没有仙人给你做。undefined紧急避孕undefined
    弱鸡程序员年底还在加班
  • 海星吧 2022-3-20
    0 7
    欧派兽 奖励三级精华
    感谢感谢。
    弱鸡程序员年底还在加班
  • 77999 2022-3-21
    0 8
    紧急避孕
    这个人很懒,什么也没有留下!
    • ACG里世界
      9
          
返回
发新帖