Home > database >  Passing element to composable function in Vue composition API?
Passing element to composable function in Vue composition API?

Time:07-05

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 };
}
  • Related