Используйте useVirtualList из VueUse для рендеринга компонента Listbox HeadlessUI

Я хочу использовать составной виртуальный скроллер VueUse для рендеринга содержимого списка HeadlessUI .

Вот что я пробовал:

      <Listbox v-model="selectedIcon">
  <div class="relative mt-1">
    <ListboxButton class="bg-white rounded-lg cursor-default shadow-md text-left w-full py-2 pr-10 pl-3 relative sm:text-sm focus:outline-none focus-visible:border-indigo-500 focus-visible:ring-white focus-visible:ring-2 focus-visible:ring-opacity-75 focus-visible:ring-offset-orange-300 focus-visible:ring-offset-2">
      <span class="block truncate">test</span>
      <span class="flex pr-2 inset-y-0 right-0 absolute items-center pointer-events-none">
        <SelectorIcon class="h-5 text-gray-400 w-5" aria-hidden="true" />
      </span>
    </ListboxButton>

    <ListboxOptions v-bind="containerProps" class="bg-white rounded-md shadow-lg ring-black mt-1 text-base w-full max-h-60 h-full py-1 ring-1 ring-opacity-5 absolute overflow-auto sm:text-sm focus:outline-none">
      <div v-bind="wrapperProps">
        <ListboxOption v-slot="{ active, selected }" v-for="icon in list" :key="icon.data.name" :value="icon">
          <li>
            <span>{{ icon.data.name }}</span>
          </li>
        </ListboxOption>
      </div>
    </ListboxOptions>
  </div>
</Listbox>

И это составной виртуальный скроллер:

      const { list, containerProps, wrapperProps } = useVirtualList(icons, { itemHeight: 40 })

Проблема в том, что когда я пытаюсь открыть список, я получаю такую ​​ошибку:

      Uncaught (in promise) TypeError: Failed to execute 'observe' on 'ResizeObserver': parameter 1 is not of type 'Element'.
    at watch.immediate (index.mjs:1322)
    at callWithErrorHandling (runtime-core.esm-bundler.js:6737)
    at callWithAsyncErrorHandling (runtime-core.esm-bundler.js:6746)
    at Array.job (runtime-core.esm-bundler.js:7154)
    at flushPostFlushCbs (runtime-core.esm-bundler.js:6938)
    at flushJobs (runtime-core.esm-bundler.js:6983)
    at flushJobs (runtime-core.esm-bundler.js:6991)

Я также получаю это предупреждение:

      [Vue warn]: Unhandled error during execution of watcher callback 
  at <ApplicationIconSelector key=0 > 
  at <Anonymous as="template" enter="ease-out duration-300" enter-from="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"  ... > 
  at <ForcePortalRoot force=false > 
  at <PortalGroup target= <div class=​"fixed z-10 inset-0 overflow-y-auto" id=​"headlessui-dialog-4" role=​"dialog" aria-modal=​"true" aria-labelledby=​"headlessui-dialog-title-8">​…​</div>​<div class=​"flex min-h-screen text-center px-4 pt-4 pb-20 items-end justify-center sm:​p-0 sm:​block">​<div id=​"headlessui-dialog-overlay-6" aria-hidden=​"true" class=​"bg-gray-975 bg-opacity-85 inset-0 transition-opacity fixed">​</div>​<!-- This element is to trick the browser into centering the modal contents. --><span class=​"hidden sm:​h-screen sm:​inline-block sm:​align-middle" aria-hidden=​"true">​&ZeroWidthSpace;​</span>​<div class=​"rounded-lg shadow-xl text-left transform transition-all text-gray-850 inline-block align-bottom sm:​max-w-lg sm:​my-8 sm:​w-full sm:​align-middle dark:​text-gray-200">​<div class=​"rounded-t-lg bg-gray-25 px-4 pt-5 pb-4 sm:​p-6 sm:​pb-4 dark:​bg-gray-925">​…​</div>​<div class=​"bg-gray-75 py-3 px-3 sm:​flex sm:​flex-row-reverse dark:​bg-gray-900">​…​</div>​flex<button class=​"flex-y-center justify-center p-2 px-3 font-medium text-sm transition duration-75 select-none cursor-pointer focus:​outline-none rounded-md bg-gray-75 text-gray-850 hover:​bg-gray-100 active:​bg-gray-175 dark:​text-gray-250 dark:​bg-gray-875 dark:​hover:​bg-gray-850 dark:​active:​bg-gray-825 w-full">​…​</button>​flex</div>​</div>​</div>​</div>​ > 
  at <Portal> 
  at <ForcePortalRoot force=true > 
  at <Dialog as="div" class="fixed z-10 inset-0 overflow-y-auto" ref="el"  ... > 
  at <Anonymous onBeforeEnter=fn<onBeforeEnter> onAfterEnter=fn<onAfterEnter> onBeforeLeave=fn<onBeforeLeave>  ... > 
  at <Anonymous as="template" show=true data=null > 
  at <AddEditApplication modelValue=true onUpdate:modelValue=fn data=null > 
  at <Index onVnodeUnmounted=fn<onVnodeUnmounted> ref=Ref< Proxy {__v_skip: true} > > 
  at <RouterView> 
  at <App>

1 ответ

Uncaught (in promise) TypeError: Failed to execute 'observe' on 'ResizeObserver': parameter 1 is not of type 'Element'.

Похоже, он пытается привязать себя к чему-то другому, кроме собственного элемента DOM. В примере на сайте VueUse показаны нативные элементы DOM с директивой. Однако ваш код использует v-bindна неродных элементах DOM у вас есть это на VNode (компонент ListBox).

Даже взглянув на исходный код, вы можете увидеть, что привязка containerPropsожидает HTMLElement.

      const containerRef: Ref = ref<HTMLElement | null>()

Раньше я не использовал HeadlessUI, но, глядя на исходный код компонента, кажется, что он не отображает никаких элементов, кроме того, что передается в его слот по умолчанию; ака твой. Ваш список классов хоть на чем-то отображается? Трудно сказать, как работает ваш код без примера.

Я рекомендую создать еще один , вложенный внутрь , который обертывает <div v-bind="wrapperProps">элемент. На этом новом divпереместить v-bind="containerProps"от ListBoxOptionsна него; Смотри ниже.

      <ListboxOptions>
  <div v-bind="containerProps" class="bg-white rounded-md shadow-lg ring-black mt-1 text-base w-full max-h-60 h-full py-1 ring-1 ring-opacity-5 absolute overflow-auto sm:text-sm focus:outline-none">
    <div v-bind="wrapperProps">
      <ListboxOption v-slot="{ active, selected }" v-for="icon in list" :key="icon.data.name" :value="icon">
        <li>
          <span>{{ icon.data.name }}</span>
        </li>
      </ListboxOption>
    </div>
  </div>
</ListboxOptions>

Я думаю, что это может решить вашу проблему.

Другие вопросы по тегам