指尖上的记忆指尖上的记忆
首页
  • 基础
  • Laravel框架
  • Symfony框架
  • 基础
  • Gin框架
  • 基础
  • Spring框架
  • 命令
  • Nginx
  • Ai
  • Deploy
  • Docker
  • K8s
  • Micro
  • RabbitMQ
  • Mysql
  • PostgreSsql
  • Redis
  • MongoDb
  • Html
  • Js
  • 前端
  • 后端
  • Git
  • 知识扫盲
  • Golang
🌟 gitHub
首页
  • 基础
  • Laravel框架
  • Symfony框架
  • 基础
  • Gin框架
  • 基础
  • Spring框架
  • 命令
  • Nginx
  • Ai
  • Deploy
  • Docker
  • K8s
  • Micro
  • RabbitMQ
  • Mysql
  • PostgreSsql
  • Redis
  • MongoDb
  • Html
  • Js
  • 前端
  • 后端
  • Git
  • 知识扫盲
  • Golang
🌟 gitHub
floatingUI的使用, 这个主要是解决弹窗等的自适应的问题, 官网:https://floating-ui.com/docs/getting-started
//usePatchSelect.ts
import {
  autoUpdate,
  flip,
  offset as offsetMiddleware,
  shift,
  useFloating,
} from "@floating-ui/vue";

export const usePatchSelect = () => {
  const id = useId();
  const wrapperElement = ref<HTMLElement | null | undefined>(null);
  const floatingElement = ref<HTMLElement | null | undefined>(null);
  const referenceElement = ref<HTMLElement | null | undefined>(null);

  const floating = useFloating(referenceElement, floatingElement, {
    placement: "bottom-start",
    middleware: [offsetMiddleware(0), shift(), flip()],
    whileElementsMounted: autoUpdate,
  });

  const onBeforeOpen = () => {
    nextTick(() => {
      wrapperElement.value = document.querySelector<HTMLElement>(
        `[data-app-select-id="${id}"]`,
      );
      referenceElement.value = wrapperElement.value?.querySelector<HTMLElement>(
        ".common-field__dropdown-input",
      );
      floatingElement.value = wrapperElement.value?.querySelector<HTMLElement>(
        ".common-field__options",
      );

      floating.update();
      wrapperElement.value?.classList.add("overflow-hidden");
    });
  };
  const onAfterClose = () => {
    floatingElement.value = null;
    floating.update();
  };

  watch(floating.floatingStyles, (styles) => {
    wrapperElement.value?.classList.remove("overflow-hidden");

    const listBox = floatingElement.value;
    if (listBox) {
      if (listBox.classList.contains("transition")) {
        listBox.classList.remove("transition");
        listBox.classList.add("transition-[opacity]");
      }

      Object.assign(listBox.style, styles);
    }
  });

  return {
    onBeforeOpen,
    onAfterClose,
    "data-app-select-id": id,
  };
};


const patchedProps = usePatchSelect();
<AppSelect
      :model-value="perPageSelection"
      class="min-w-[8rem] md:!w-auto"
      :items="perPageOptions"
      v-bind="patchedProps" //重要的是这个,会把usePatchSelect中暴露的 "data-app-select-id": id 绑定到这个元素(有个data-app-select-id属性),然后后面所有的操作都是基于这个id进行的
      @update:model-value="emit('changePerPage', $event as MSelectItem<number>)"
    />


<!-- AppSelect.vue -->
<template>
  <div class="app-select-wrapper" v-bind="$attrs"> // vue3使用这个v-bind="$attrs" 来获取需要绑定的属性,这里是data-app-select-id
    <!-- dropdown, input, etc -->
  </div>
</template>