// pagination list, load more (or lazy load)
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);
});
}
// usage
useScrollToBottom(() => { console.log('Scrolled to bottom') })
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);
});
}
// usage
<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>
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
}
}
// usage
const { device } = useViewport({ mobile: 700, table: 900 });
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;
}
}
// usage
const copyToClipboard = useCopyToClipboard();
copyToClipboard('just copy');
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);
})
}
// usage
useNetworkStatus((status) => {
console.log(`Your network status is ${status}`);
}
// https://javascript.plainenglish.io/10-useful-custom-hooks-with-vue-js-37f0fd42ce0d
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)
]
}
// usage
const [token, setToken] = useStorage('token');
setToken('new token');
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
}
}
// usage
setup() {
const { width, height } = useWindowResize();
}
<body>
<input type="color" id="color" value="#c1e0ff" />
</body>
<script>
const color = document.querySelector('#color')
const div = document.body
color.addEventListener('input', () => {
div.style.backgroundColor = color.value
})
color.dispatchEvent(new Event('input'));
</script>
const generateRandomHexColor = () =>
`#${Math.floor(Math.random() * 0xffffff).toString(16)}`;
const scrollToTop = (element) =>
element.scrollIntoView({ behavior: "smooth", block: "start" });
const scrollToBottom = (element) =>
element.scrollIntoView({ behavior: "smooth", block: "end" });