十个有用的 Vue.js 自定义 Hook

Vue.js 是我使用的第一个 JavaScript 框架。 我可以说 Vue.js 是我进入 JavaScript 世界的第一扇门之一。 

目前,Vue.js 仍然是一个很棒的框架。 我认为有了组合 API,Vue.js 只会增长得更多。 在本文中,我将向分享 10 个可以使用 Vue.js 制作的有用的自定义钩hook。

01、使用窗口调整大小

这是一个基本的hook。 因为它在许多项目中使用,并且使用纯 JavaScript 或任何框架构建它太容易了。 

与 Vue 相同,只需几行代码即可构建它。 

这是我的代码:

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}
}

不仅构建简单,而且使用起来也很容易。 只需要调用这个钩子即可获取窗口的宽度和高度:

setup() {const { width, height } = useWindowResize();
}

 

02、使用存储

您想通过将数据值存储在会话存储或本地存储中并将该值绑定到视图来持久保存数据吗? 只需一个简单的hook——useStorage,一切就变得如此简单。 

我们只需要创建一个hook,返回从存储中获取的数据,以及一个在我们想要更改数据时将数据存储在存储中的函数。 

这是我的代码。

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 来格式化数据。 

如果您不想格式化它,可以将其删除。 这是如何使用此hook的示例。

const [token, setToken] = useStorage('token');
setToken('new token');
  • 1.
  • 2.
03、使用网络状态

这是一个有用的hook,支持检查网络连接的状态。 为了实现这个hook,我们需要为“在线”和“离线”事件添加事件监听器。 

在事件中,我们只是调用一个回调函数,参数为网络状态。 

这是我的代码:

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);})
}

只是简单易用。 

目前,我使用参数“online”/“offline”调用回调函数。 您可以将其更改为真/假或任何您想要的。

useNetworkStatus((status) => { console.log(`Your network status is ${status}`);
}

 

04、使用复制到剪贴板

将文本复制到剪贴板是每个项目中都很流行的功能。 我知道我们可以创建一个函数来代替钩子来做到这一点。 

但我喜欢数字 10,所以我决定在这篇文章中加入这个hook。 这个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;}
}

在我的代码中,我在函数 copyToClipboard 中将逻辑复制文本放入剪贴板。 我知道我们有很多方法可以做到这一点。 你可以在此功能中尝试最适合你的方法。 

至于如何使用,调用即可。

const copyToClipboard = useCopyToClipboard();
copyToClipboard('just copy');
05、使用主题

只需一个简短的钩子即可更改网站的主题。 它可以帮助我们轻松切换网站的主题,只需用主题名称调用此hook即可。 这是我用来定义主题变量的 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');
06、使用页面可见性

有时,当客户不关注我们的网站时,我们需要做一些事情。 为此,我们需要一些东西来让我们知道用户是否集中注意力。 这是一个定制的hook。 

我称之为 usePageVisibility,下面是该hook的代码:

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);});
}

 

要使用这个hook,我们只需要创建一个带有客户端隐藏状态(焦点状态)参数的回调函数。

usePageVisibility((hidden) => {console.log(`User is${hidden ? ' not' : ''} focus your site`);
});

 

07、使用视口

在第一个自定义hook中,我们构建了useWindowRezie,它可以帮助我们查看窗口的当前宽度和高度。 

我认为这对于那些想要构建适用于多种屏幕尺寸的东西的人很有帮助。 

在我处理过的案例中,我们经常使用宽度来检测当前用户设备。 它可以帮助我们在他们的设备上安装一些东西。 

在此hook中,我将使用 useWindowResize 构建相同的内容,但它返回设备名称而不是宽度和高度值。 

这是这个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}
}

它是如此容易。 除了默认的设备尺寸之外,当我们使用包含手机和平板电脑尺寸的参数对象调用该hook时,用户可以修改它。 这是我们使用它的方式:

const { device } = useViewport({ mobile: 700, table: 900 });

 

08、使用OnClickOutside

目前,模态被用于许多应用程序中。 它对于许多用例(表单、确认、警告等)确实很有帮助。 

我们经常用它处理的流行操作之一是用户在模式之外单击。 useOnClickOutside 对于这种情况是一个有用的hook。 

我们只需要一个 ref 元素、回调函数并将其绑定到窗口事件中。 这是我的代码(适用于桌面和移动设备):

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);});
}

 

正如我所说,要使用它,我们只需要使用参数 ref 元素和回调函数来调用它。

<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>

 

09、使用滚动到底部

除了分页列表之外,加载更多(或延迟加载)是加载数据的一种友好方式。 特别是对于移动设备,几乎在移动设备上运行的应用程序都会在其 UI 中加载更多负载。 为此,我们需要检测用户滚动到列表底部并触发该事件的回调。 

useScrollToBottom 是一个有用的hook来支持您这样做。 这是我构建该hook的代码:

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);});
}

在我的hook中,我通过条件“((window.innerHeight + window.scrollY) >= document.body.scrollHeight)”检测到底部。 

我们有很多方法来检测它。 如果您的项目符合其他条件,我们就使用它们。 以下是如何使用此hook的示例:

useScrollToBottom(() => { console.log('Scrolled to bottom') })

 

10、使用定时器

最后,我们来到最后一个钩子。 这个钩子的代码比其他钩子要长一些。 useTimer 将支持我们运行带有一些选项的计时器,例如开始、暂停/恢复、停止。 

为此,我们需要使用 setInterval 方法,在该方法中,我们将推送处理函数。 在那里,我们需要检查计时器的暂停状态。 

如果计时器没有暂停,我们只需要调用一个回调函数,该函数由用户作为参数传递。 

为了支持用户了解该计时器的当前暂停状态,除了 useTimer 操作之外,还为他们提供一个变量 isPaused ,其值作为计时器的暂停状态。 

这是我构建该hook的代码:

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}
}

这是使用 useTimer hook的一种方法:

function handleTimer(round) {      roundNumber.value = round;    
}
const { start,stop,pause,resume,isPaused
} = useTimer(handleTimer);

到这里,我已经跟大家分享了10 个有用的 Vue.js hook。 我认为它们的构建和使用都很简单。 我只是为那些想要在 Vue.js 中使用这些钩子的人提供一些注释。

请记住删除要添加到窗口的事件。 Vue 为我们提供了一个有用的组合 API onUnmounted ,它可以帮助我们在卸载hook之前运行我们的操作。 

在我构建的每个钩子中,我总是删除 onUnmounted 中的事件侦听器。

仅在真正需要时才使用反应变量。 如果您想使用一个存储某些内容的变量,并且希望在数据更改时同步其数据,那么,让我们使用反应式变量。 

但如果它只是一个在我们的hook中存储数据的变量(计数器、标志......),我认为你不需要使用反应变量。

如果可以的话,不要在钩子中进行硬编码(设置固定值)。 

我认为我们只需要将逻辑存储在我们的hook中。 关于配置值,我们应该让用户填写它(例如:useViewport)。

最后,在我的文章中,我与您分享了10 个有用的 Vue 自定义hook,我希望它们对您有所帮助。 Vue.js 是一个很棒的框架,我希望你可以用它构建更多很棒的东西。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/146445.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

2023年中国火化设备行业现状分析:随着城市化进程的推进,市场需求将持续增长[图]

火化设备行业是指生产和提供用于尸体火化处理的设备和相关服务的行业。火化设备主要用于将尸体进行高温焚烧&#xff0c;将尸体转化为骨灰&#xff0c;以达到尸体处理和殡葬的目的。 火化设备行业优点 资料来源&#xff1a;共研产业咨询&#xff08;共研网&#xff09; 我国火…

【农业生产模拟】WOFOST模型与PCSE模型实践

查看原文>>>【农业生产模拟】WOFOST模型与PCSE模型实践 WOFOST&#xff08;WorldFoodStudies&#xff09;和PCSE&#xff08;PythonCropSimulationEnvironment&#xff09;是两个用于农业生产模拟的模型&#xff1a;WOFOST是一个经过多年开发和验证的模型&#xff0c…

【随笔记】C++ condition_variable 陷阱

问题说明 通过 std::condition_variable 来实现超时等待&#xff0c;会受到系统时间变化的影响&#xff0c;系统时间倒退修改就会导致延后唤醒&#xff0c;系统时间提前将会导致提前被唤醒&#xff0c;返回结果仍为超时。 这种问题只有在系统时间发生变化的时候才会出现&…

LeNet网络复现

文章目录 1. LeNet历史背景1.1 早期神经网络的挑战1.2 LeNet的诞生背景 2. LeNet详细结构2.1 总览2.2 卷积层与其特点2.3 子采样层&#xff08;池化层&#xff09;2.4 全连接层2.5 输出层及激活函数 3. LeNet实战复现3.1 模型搭建model.py3.2 训练模型train.py3.3 测试模型test…

借助Log360实现综合可见性的增强网络安全

当今的企业对技术的依赖程度前所未有&#xff0c;因此强大的威胁检测和响应策略变得至关重要。在现代世界中&#xff0c;网络犯罪分子不断寻找新的、富有创意的方式&#xff0c;以侵入组织的网络并窃取敏感数据。综合性的可见性是一个关键要素&#xff0c;有时被忽视&#xff0…

Unity HDRP Custom Pass 实现场景雪地效果

先使用Shader Graph连一个使用模型法线添加雪地的shader&#xff0c;并赋给一个material。 1.1 先拿到模型世界坐标下的顶点法线&#xff0c;简单处理一下&#xff0c;赋给透明度即可。 给场景添加Custom Pass&#xff0c;剔除不需要的层级。 1.在Hierarchy界面中&#xff…

Wi-Fi直连分享:Android设备间的高速连接

Wi-Fi直连分享&#xff1a;Android设备间的高速连接 引言 随着无线局域网&#xff08;Wi-Fi&#xff09;的普及和发展&#xff0c;使用Wi-Fi直连技术&#xff08;P2P&#xff09;在没有中间接入点的情况下实现设备间直接互联成为可能。通过Wi-Fi直连&#xff0c;具备相应硬件…

【React】React组件生命周期以及触发顺序(部分与vue做比较)

最近在学习React&#xff0c;发现其中的生命周期跟Vue有一些共同点&#xff0c;但也有比较明显的区别&#xff0c;并且执行顺序也值得讨论一下&#xff0c;于是总结了一些资料在这里&#xff0c;作为学习记录。 v17.0.1后生命周期图片 初始化阶段 由ReactDOM.render()触发 —…

【Java 进阶篇】JDBC插入数据详解

在Java应用程序中&#xff0c;与数据库交互是一项常见的任务。其中&#xff0c;插入数据操作是一种基本的数据库操作之一。本文将详细介绍如何使用Java JDBC&#xff08;Java Database Connectivity&#xff09;来执行插入数据操作。无论您是初学者还是有一定经验的开发人员&am…

CSS详细基础(六)边框样式

本期是CSS基础的最后一篇~ 目录 一.border属性 二.边框属性复合写法 三.CSS修改表格标签 四.内边距属性 五.外边距属性 六.其他杂例 1.盒子元素水平居中 2.清除网页内外元素边距 3.外边距的合并与塌陷 4.padding不会撑大盒子的情况 七.综合案例——新浪导航栏仿真 …

Android studio升级Giraffe | 2022.3.1 Patch 1踩坑

这里写自定义目录标题 not "opens java.io" to unnamed module错误报错信息解决 superclass access check failed: class butterknife.compiler.ButterKnifeProcessor$RScanner报错报错信息解决 Android studio升级Giraffe | 2022.3.1 Patch 1后&#xff0c;出现项目…

imgui开发笔记<1>、ubuntu环境下快速应用

去这个链接下载imgui源码&#xff08;在此之前需要安装opengl glfw3等等&#xff09;&#xff1a; sudo apt-get install libglfw3-dev https://github.com/ocornut/imgui 我这里源码下载到/home/temp/imgui目录下&#xff0c;咱们不需要编译源码成库&#xff0c;而是直接将下…

【Axure高保真原型】3D圆柱图_中继器版

今天和大家分享3D圆柱图_中继器版的原型模板&#xff0c;图表在中继器表格里填写具体的数据&#xff0c;调整坐标系后&#xff0c;就可以根据表格数据自动生成对应高度的圆柱图&#xff0c;鼠标移入时&#xff0c;可以查看对应圆柱体的数据……具体效果可以打开下方原型地址体验…

网络安全渗透测试工具之skipfish

网络安全渗透测试工具skipfish介绍 在数字化的时代,Web 应用程序安全成为了首要任务。想象一下,您是一位勇敢的安全冒险家,迎接着那些隐藏在 Web 应用程序中的未知风险。而在这个冒险之旅中,您需要一款强大的工具来帮助您发现漏洞,揭示弱点。而这个工具就是 Skipfish。 …

LeetCode 周赛上分之旅 #48 一道简单的树上动态规划问题

⭐️ 本文已收录到 AndroidFamily&#xff0c;技术和职场问题&#xff0c;请关注公众号 [彭旭锐] 和 BaguTree Pro 知识星球提问。 学习数据结构与算法的关键在于掌握问题背后的算法思维框架&#xff0c;你的思考越抽象&#xff0c;它能覆盖的问题域就越广&#xff0c;理解难度…

点击、拖拉拽,BI系统让业务掌握数据分析主动权

在今天的商业环境中&#xff0c;数据分析已经成为企业获取竞争优势的关键因素之一。然而&#xff0c;许多企业在面对复杂的数据分析工具时&#xff0c;却常常感到困扰。这些工具往往需要专业的技术人员操作&#xff0c;而且界面复杂&#xff0c;难以理解和使用。对业务人员来说…

阿里云 Oss 权限控制

前言 最近公司的私有 Oss 服务满了&#xff0c;且 Oss 地址需要设置权限&#xff0c;只有当前系统的登录用户才能访问 Oss 下载地址。一开始想着用 Nginx 做个转发来着&#xff0c;Nginx 每当检测当前请求包含特定的 Oss 地址就转发到我们的统一鉴权接口上去&#xff0c;但是紧…

picoctf_2018_shellcode

picoctf_2018_shellcode Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX disabled PIE: No PIE (0x8048000) RWX: Has RWX segments32位&#xff0c;啥都没开 这个看着挺大的&#xff0c;直接来个ROPchain&#xff0c;…

Redis缓存穿透、击穿和雪崩

面试高频 服务的高可用问题&#xff01; 在这里我们不会详细的区分析解决方案的底层&#xff01; Redis缓存概念 Redis缓存的使用&#xff0c;极大的提升了应用程序的性能和效率&#xff0c;特别是数据查询方面。但同时&#xff0c;它也带来了一些问题。其中&#xff0c;最要…