I'll preface this question by saying I'm very new to the composition API so I'm still trying to figure out the best practices. I'm writing a useResizeObserver
composable function using Vue's composition API in order to track dimension changes on a target element. Because I have to wait for the element to be mounted, I can't call my composable from top-level in the setup()
method on my component as most examples show, but have to call it from onMounted()
instead, where I have access to my element's ref
.
onMounted(async () => {
elementDimensions.value = useResizeObserver(modalContent.value);
}
This forced me to have another ref
that I named elementDimensions
actually declared at the top level of the setup()
function, which I initialise to null
.
setup(props) {
const elementDimensions = ref(null);
const modalContent = ref(null);
...
}
Here is the useResizeObserver
function itself:
export default function useResizeObserver(element) {
const elementHeight = ref(0);
const elementWidth = ref(0);
const resizeObserver = new ResizeObserver(entries => {
elementHeight.value = entries[0].contentRect.height;
elementWidth.value = entries[0].contentRect.width;
});
if (element) {
resizeObserver.observe(element);
}
onUnmounted(() => {
resizeObserver.disconnect();
});
return { elementHeight, elementWidth };
}
This actually works well to give me what I want but I'm wondering if there's a better way to achieve this. The way things are implemented right now, I end up with "nested" refs, since I end up wrapping elementHeight
and elementWidth
(which are already refs) into another ref inside the component (elementDimensions
). Is there a better recommended way of doing this when you need to pass an element to a composable from onMounted()
?
CodePudding user response:
Composition functions are supposed to be used directly in setup
, any other uses depend on the implementation and need to be verified.
Refs are basically objects that allow to pass a value by reference rather than by value. One of their uses is to pass a ref early and access when a value is up-to-date.
It should be:
setup(props) {
const modalContent = ref(null);
const elementDimensions = useResizeObserver(modalContent);
...
}
and
export default function useResizeObserver(element) {
const elementHeight = ref(0);
const elementWidth = ref(0);
let resizeObserver;
onMounted(() => {
if (element.value) {
resizeObserver = new ResizeObserver(...);
resizeObserver.observe(element.value);
}
}
onUnmounted(() => {
if (resizeObserver)
resizeObserver.disconnect();
});
return { elementHeight, elementWidth };
}