作者:Sang Nguyen
译者:前端小智
起源:medium
有幻想,有干货,微信搜寻 【大迁世界】 关注这个在凌晨还在刷碗的刷碗智。
本文 GitHub https://github.com/qq449245884/xiaozhi 已收录,有一线大厂面试残缺考点、材料以及我的系列文章。
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。
原文:https://javascript.plainengli...
交换
有幻想,有干货,微信搜寻 【大迁世界】 关注这个在凌晨还在刷碗的刷碗智。
本文 GitHub https://github.com/qq449245884/xiaozhi 已收录,有一线大厂面试残缺考点、材料以及我的系列文章。