NUXT: Accessing DOM in a composable
About a 4 minute read
Written by Kyle Hawk on Mar 7, 2024
#nuxt #vue
So I’m learning Nuxt, right?
Well they have these neat things called composables. These are files that perform some sort of action and can be accessed throughout the application. I like to think of them as global helper functions… but I’m sure someone would tell me that’s wrong.
Anyway. I spent way too long stuck on a recent problem. I wanted to access the DOM via a composable. The problem was I kept getting an error because the composable was being executed before the DOM was created.
Classic, right?
The solution was pretty simple and something I didn’t even know you could do: lifecycle hooks. You can use Vue lifecycle hooks in your composable.
Simple DOM event listener
let scrollDir = "";
let lastScroll = window.scrollY || document.documentElement.scrollTop;
document.addEventListener("scroll", () => {
let scr = window.scrollY || document.documentElement.scrollTop;
scrollDir = scr > lastScroll ? "down" : "up";
lastScroll = scr;
});
Simple, right? Compare the current scroll value to the previous one to determine up or down and store that value in the scrollDir
variable.
This could be used in each component that needs the value, but that would get messy in a hurry. So let’s make it reusable by putting it in a composable and storing the directional value with useState
.
export const useScrollDirection = () => {
let lastScroll = window.scrollY || document.documentElement.scrollTop;
document.addEventListener("scroll", () => {
let scr = window.scrollY || document.documentElement.scrollTop;
dir.value = scr > lastScroll ? "down" : "up";
lastScroll = scr;
});
let dir = useState("scrollDirection", () => "");
return dir;
};
Now we can use this composable in our components like this:
const scrollDirection = useScrollDirection();
Now… we have all the logic in one composable, and can access the information from anywhere in our application, except there’s one problem. This code will error due to the issue stated above. The composable will fire before the DOM is created, resulting in an error.
Lifecycle events in composable
Luckily, the solution is easy. Wrap the code within the onMounted
lifecycle hook. This will make sure the DOM exists when we add the scroll event listener and solve our error.
export const useScrollDirection = () => {
onMounted(() => {
let lastScroll = window.scrollY || document.documentElement.scrollTop;
document.addEventListener("scroll", () => {
let scr = window.scrollY || document.documentElement.scrollTop;
dir.value = scr > lastScroll ? "down" : "up";
lastScroll = scr;
});
});
let dir = useState("scrollDirection", () => "");
return dir;
};
TADA! It took me way too long to figure out you could use lifecycle hooks in composables. Hopefully this helps someone out there that was like me.