Author: Sang Nguyen
Translator: Front-end Xiaozhi Source: medium
If you have dreams and dry goods, you can search for [Great Move to the World] on WeChat and pay attention to this Shawanzhi who is still washing dishes in the early hours of the morning.
This article GitHub https://github.com/qq449245884/xiaozhi has been included, there are complete test sites, materials and my series of articles for interviews with first-line manufacturers.
Vue was the first JS framework I used. It can be said that Vue was one of my first doors into the JavaScript world. For now, Vue is still a great framework. With the advent of the composition API, Vue will only grow even more. In this article, I will introduce 10 useful custom hooks to make our code look better.
useWindowResize
This is a basic hook as it is used in many projects.
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
}
}
It's easier to use, just call this hook to get the width and height of the window.
setup() {
const { width, height } = useWindowResize();
}
useStorage
Do you want to persist data by storing its value in session storage or local storage and bind that value to the view? With a simple hook -- useStorage , this becomes very easy. We just need to create a hook to return the data obtained from the storage space, and a function to store the data in the storage space when we want to change it. Below is my 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)
]
}
In my code I use JSON.parse and JSON.stringify to format the data. If you don't want to format it, you can delete it. Below is an example of how to use this hook.
const [token, setToken] = useStorage('token');
setToken('new token');
useNetworkStatus
This is a useful hook that supports checking the status of network connections. To implement this hook, we need to add event listeners for the events "online" and "offline". In the event, we just call a callback function with the network state as an argument. Below is my code.
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);
})
}
Call method:
useNetworkStatus((status) => {
console.log(`Your network status is ${status}`);
}
useCopyToClipboard
The clipboard is a relatively common function, we can also encapsulate it as a hook, the code is as follows:
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;
}
}
Use as follows:
const copyToClipboard = useCopyToClipboard();
copyToClipboard('just copy');
useTheme
Just a short hook to change the theme of the site. It helps us to switch the theme of the website easily, just call this hook with the theme name. Below is an example of the CSS code I used to define the theme variables.
html[theme="dark"] {
--color: #FFF;
--background: #333;
}
html[theme="default"], html {
--color: #333;
--background: #FFF;
}
To change the theme, just make a custom hook that returns a function to change the theme by the theme name. code show as below:
export const useTheme = (key = '') => {
return (theme) => {
document.documentElement.setAttribute(key, theme);
}
}
Use as follows:
const changeTheme = useTheme();
changeTheme('dark');
usePageVisibility
Sometimes we need to do something when a client is not focused on our website. To do this, we need something that lets us know if the user is paying attention. This is a custom hook. I called it PageVisibility
and the code is as follows:
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);
});
}
The usage is as follows:
usePageVisibility((hidden) => {
console.log(`User is${hidden ? ' not' : ''} focus your site`);
});
useViewport
Sometimes we use the width to detect the current user device, so that we can process the corresponding content according to the device. In this scenario, we can also encapsulate it into a hook, the code is as follows:
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
}
}
Use as follows:
const { device } = useViewport({ mobile: 700, table: 900 });
useOnClickOutside
When the model box pops up, we want to click on other areas to close it. This can be done using clickOutSide. We can also encapsulate this scenario as a hook. The code is as follows:
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);
});
}
The usage is as follows:
<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
Besides paginated lists, loading more (or lazy loading) is a friendly way to load data. Especially for mobile devices, almost all applications running on mobile devices have load more applied in their user interface. To do this, we need to detect that the user scrolled to the bottom of the list and fire a callback for that event. useScrollToBottom
is a useful hook that allows you to do this. code show as below:
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);
});
}
The usage is as follows:
useScrollToBottom(() => { console.log('Scrolled to bottom') })
useTimer
The code for useTimer is a bit longer than other hooks. useTimer
Support running a timer with some options like start, pause/resume, stop. To do this, we need to use the setInterval
method. Here, we need to check the paused state of the timer. If the timer is not paused, we just need to call a callback function, which is passed by the user as a parameter. In order to support users to understand the current pause state of the timer, in addition to action useTimer, they should also be given a variable isPaused
whose value is the pause state of the timer. code show as below:
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
}
}
The usage is as follows:
function handleTimer(round) {
roundNumber.value = round;
}
const {
start,
stop,
pause,
resume,
isPaused
} = useTimer(handleTimer);
This article shares 10 useful Vue custom hooks. Hope they are helpful to you. Vue. is a great framework, hope you can use it to build more great things.
The bugs that may exist after the code is deployed cannot be known in real time. In order to solve these bugs afterwards, a lot of time is spent on log debugging. By the way, I recommend a useful bug monitoring tool , Fundebug .
Original: https://javascript.plainenglish.io/10-useful-custom-hook-with-vue-js-37f0fd42ce0d
comminicate
If you have dreams and dry goods, you can search for [Great Move to the World] on WeChat and pay attention to this Shawanzhi who is still washing dishes in the early hours of the morning.
This article GitHub https://github.com/qq449245884/xiaozhi has been included, there are complete test sites, materials and my series of articles for interviews with first-line manufacturers.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。