有梦想,有干货,微信搜索
【大迁世界】
关注这个在凌晨还在刷碗的刷碗智。
本文 GitHub
github.com/qq449245884…
已收录,有一线大厂面试完整考点、资料以及我的系列文章。
Vue 是我使用的第一个 JS 框架。可以说,Vue 是我进入JavaScript世界的第一道门之一。目前,Vue 仍然是一个很棒的框架。随着 composition API 的出现,Vue 只会有更大的发展。在这篇文章中,我将介绍 10 个有用的自定义钩子,让我们的代码更加好看。
useWindowResize
这是一个基本的钩子,因为它被用在很多项目中.
import { ref, onMounted, onUnmounted } from 'vue';
export function useWindowResize() {
const width = ref(window.innerWidth);
const height = ref(window.innerHeight);
const handleResize = () => {
width.value = window.innerWidth;
height.value = window.innerHeight;
onMounted(() => {
window.addEventListener('resize', handleResize)
onUnmounted(() => {
window.removeEventListener('resize', handleResize)
return {
width,
height
使用就更简单了,只需要调用这个钩子就可以获得 window 的宽度和高度。
setup() {
const { width, height } = useWindowResize();
useStorage
你想通过在 session storage 或 local storage 中存储数据的值来持久化数据,并将该值绑定到视图?有了一个简单的钩子--useStorage,这将变得非常容易。我们只需要创建一个钩子来返回从存储空间得到的数据,以及一个函数来在我们想要改变数据时将其存储在存储空间。下面是我的钩子。
import { ref } from 'vue';
const getItem = (key, storage) => {
let value = storage.getItem(key);
if (!value) {
return null;
try {
return JSON.parse(value)
} catch (error) {
return value;
export const useStorage = (key, type = 'session') => {
let storage = null;
switch (type) {
case 'session':
storage = sessionStorage;
break;
case 'local':
storage = localStorage;
break;
default:
return null;
const value = ref(getItem(key, storage));
const setItem = (storage) => {
return (newValue) => {
value.value = newValue;
storage.setItem(key, JSON.stringify(newValue));
return [
value,
setItem(storage)
在我的代码中,我使用 JSON.parse ** 和 JSON.stringify** 来格式化数据。如果你不想格式化它,你可以删除它。下面是一个如何使用这个钩子的例子。
const [token, setToken] = useStorage('token');
setToken('new token');
useNetworkStatus
这是一个有用的钩子,支持检查网络连接的状态。为了实现这个钩子,我们需要为事件 "在线"和 "离线"添加事件监听器。在事件中,我们只是调用一个回调函数,参数为网络状态。下面是我的代码。
import { onMounted, onUnmounted } from 'vue';
export const useNetworkStatus = (callback = () => { }) => {
const updateOnlineStatus = () => {
const status = navigator.onLine ? 'online' : 'offline';
callback(status);
onMounted(() => {
window.addEventListener('online', updateOnlineStatus);
window.addEventListener('offline', updateOnlineStatus);
onUnmounted(() => {
window.removeEventListener('online', updateOnlineStatus);
window.removeEventListener('offline', updateOnlineStatus);
调用方式:
useNetworkStatus((status) => {
console.log(`Your network status is ${status}`);
useCopyToClipboard
剪切板是一个比较常见的功能,我们也可以将它封装成 hook,代码如下所示:
function copyToClipboard(text) {
let input = document.createElement('input');
input.setAttribute('value', text);
document.body.appendChild(input);
input.select();
let result = document.execCommand('copy');
document.body.removeChild(input);
return result;
export const useCopyToClipboard = () => {
return (text) => {
if (typeof text === "string" || typeof text == "number") {
return copyToClipboard(text);
return false;
使用如下:
const copyToClipboard = useCopyToClipboard()
copyToClipboard('just copy')
useTheme
只是一个简短的钩子来改变网站的主题。它可以帮助我们轻松地切换网站的主题,只需用主题名称调用这个钩子。下面是一个我用来定义主题变量的CSS代码例子。
html[theme="dark"] {
--color: #FFF;
--background: #333;
html[theme="default"], html {
--color: #333;
--background: #FFF;
要改变主题,只需要做一个自定义的钩子,它返回一个函数来通过主题名称改变主题。代码如下:
export const useTheme = (key = '') => {
return (theme) => {
document.documentElement.setAttribute(key, theme);
使用如下:
const changeTheme = useTheme()
changeTheme('dark')
usePageVisibility
有时,当客户不专注于我们的网站时,我们需要做一些事情。要做到这一点,我们需要一些东西,让我们知道用户是否在关注。这是一个自定义的钩子。我把它叫做 PageVisibility
,代码如下:
import { onMounted, onUnmounted } from 'vue'
export const usePageVisibility = (callback = () => { }) => {
let hidden, visibilityChange
if (typeof document.hidden !== "undefined") {
hidden = "hidden"
visibilityChange = "visibilitychange"
} else if (typeof document.msHidden !== "undefined") {
hidden = "msHidden"
visibilityChange = "msvisibilitychange"
} else if (typeof document.webkitHidden !== "undefined") {
hidden = "webkitHidden"
visibilityChange = "webkitvisibilitychange"
const handleVisibilityChange = () => {
callback(document[hidden])
onMounted(() => {
document.addEventListener(visibilityChange, handleVisibilityChange, false)
onUnmounted(() => {
document.removeEventListener(visibilityChange, handleVisibilityChange)
用法如下:
usePageVisibility((hidden) => {
console.log(`User is${hidden ? ' not' : ''} focus your site`);
useViewport
有时我们会用宽度来检测当前的用户设备,这样我们就可以根据设备来处理对应的内容。这种场景,我们也可以封装成一个 hook,代码如下:
import { ref, onMounted, onUnmounted } from 'vue';
export const MOBILE = 'MOBILE'
export const TABLET = 'TABLET'
export const DESKTOP = 'DESKTOP'
export const useViewport = (config = {}) => {
const { mobile = null, tablet = null } = config;
let mobileWidth = mobile ? mobile : 768;
let tabletWidth = tablet ? tablet : 922;
let device = ref(getDevice(window.innerWidth));
function getDevice(width) {
if (width < mobileWidth) {
return MOBILE;
} else if (width < tabletWidth) {
return TABLET;
return DESKTOP;
const handleResize = () => {
device.value = getDevice(window.innerWidth);
onMounted(() => {
window.addEventListener('resize', handleResize);
onUnmounted(() => {
window.removeEventListener('resize', handleResize);
return {
device
使用如下:
const { device } = useViewport({ mobile: 700, table: 900 });
useOnClickOutside
当 model 框弹出时,我们希望能点击其它区域关闭它,这个可以使用 clickOutSide,这种场景我们也可以封装成钩子,代码如下:
import { onMounted, onUnmounted } from 'vue';
export const useOnClickOutside = (ref = null, callback = () => {}) => {
function handleClickOutside(event) {
if (ref.value && !ref.value.contains(event.target)) {
callback()
onMounted(() => {
document.addEventListener('mousedown', handleClickOutside);
onUnmounted(() => {
document.removeEventListener('mousedown', handleClickOutside);
用法如下:
<template>
<div ref="container">View</div>
</template>
<script>
import { ref } from 'vue';
export default {
setup() {
const container = ref(null);
useOnClickOutside(container, () => {
console.log('Clicked outside');
</script>
useScrollToBottom
除了分页列表,加载更多(或懒惰加载)是一种友好的加载数据的方式。特别是对于移动设备,几乎所有运行在移动设备上的应用程序都在其用户界面中应用了load more。要做到这一点,我们需要检测用户滚动到列表底部,并为该事件触发一个回调。 useScrollToBottom
是一个有用的钩子,支持你这样做。代码如下:
import { onMounted, onUnmounted } from 'vue';
export const useScrollToBottom = (callback = () => { }) => {
const handleScrolling = () => {
if ((window.innerHeight + window.scrollY) >= document.body.scrollHeight) {
callback();
onMounted(() => {
window.addEventListener('scroll', handleScrolling);
onUnmounted(() => {
window.removeEventListener('scroll', handleScrolling);
用法如下:
useScrollToBottom(() => { console.log('Scrolled to bottom') })
useTimer
useTimer 的代码比其他钩子要长一些。 useTimer
支持运行一个带有一些选项的定时器,如开始、暂停/恢复、停止。要做到这一点,我们需要使用 setInterval
方法。在这里,我们需要检查定时器的暂停状态。如果定时器没有暂停,我们只需要调用一个回调函数,该函数由用户作为参数传递。为了支持用户了解该定时器当前的暂停状态,除了action useTimer之外,还要给他们一个变量 isPaused
,其值为该定时器的暂停状态。代码如下:
import { ref, onUnmounted } from 'vue'
export const useTimer = (callback = () => { }, step = 1000) => {
let timerVariableId = null
let times = 0
const isPaused = ref(false)
const stop = () => {
if (timerVariableId) {
clearInterval(timerVariableId)
timerVariableId = null
resume()
const start = () => {
stop()
if (!timerVariableId) {
times = 0
timerVariableId = setInterval(() => {
if (!isPaused.value) {
times++
callback(times, step * times)
}, step)
const pause = () => {
isPaused.value = true
const resume = () => {
isPaused.value = false
onUnmounted(() => {
if (timerVariableId) {
clearInterval(timerVariableId)
return {
start,
stop,
pause,
resume,
isPaused
用法如下:
function handleTimer(round) {
roundNumber.value = round;
const {
start,
stop,
pause,
resume,
isPaused
} = useTimer(handleTimer);
本文分享了10个有用的Vue自定义钩子。希望它们对你有帮助。Vue. 是一个很棒的框架,希望你能用它来构建更多很棒的东西。
代码部署后可能存在的BUG没法实时知道,事后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给大家推荐一个好用的BUG监控工具 Fundebug。
原文:javascript.plainenglish.io/10-useful-c…
有梦想,有干货,微信搜索 【大迁世界】 关注这个在凌晨还在刷碗的刷碗智。
本文 GitHub github.com/qq449245884… 已收录,有一线大厂面试完整考点、资料以及我的系列文章。
- 28.5w
-
华为云开发者联盟
JavaScript
- 2.9w
-
yeyan1996
JavaScript
- 63.4w
-
11044
非优秀程序员
JavaScript
- 266
-
hahajin
React.js
Vue.js