Skip to content

Vue

该包为 @floating-ui/dom 提供了 Vue 绑定,该库为浮动元素提供锚定位,以将其定位在给定参考元素旁边。

¥This package provides Vue bindings for @floating-ui/dom — a library that provides anchor positioning for a floating element to position it next to a given reference element.

npm install @floating-ui/vue

用法

¥Usage

useFloating() 是主要可组合项:

¥useFloating() is the main composable:

<script setup>
import {ref} from 'vue';
import {useFloating} from '@floating-ui/vue';
 
const reference = ref(null);
const floating = ref(null);
const {floatingStyles} = useFloating(reference, floating);
</script>
 
<template>
  <button ref="reference">Button</button>
  <div ref="floating" :style="floatingStyles">Tooltip</div>
</template>

默认情况下,这会将浮动 Tooltip 元素定位在 Button 元素的底部中心。

¥This will position the floating Tooltip element at the bottom center of the Button element by default.

  • reference 是用于定位的参考(或锚点)元素。

    ¥reference is the reference (or anchor) element that is being referred to for positioning.

  • floating 是相对于参考元素定位的浮动元素。

    ¥floating is the floating element that is being positioned relative to the reference element.

  • floatingStyles 是应用于浮动元素的 style 属性的定位样式的对象。

    ¥floatingStyles is an object of positioning styles to apply to the floating element’s style attribute.

禁用变换

¥Disabling transform

默认情况下,浮动元素使用 floatingStyles 对象中的 transform 进行定位。这是定位元素的最高效的方法,但可以禁用:

¥By default, the floating element is positioned using transform in the floatingStyles object. This is the most performant way to position elements, but can be disabled:

useFloating(reference, floating, {
  transform: false,
});

如果你想在允许变换动画的同时保留变换样式,请创建一个封装器,其中最外层的节点是定位的节点,内部的节点是实际的样式元素。

¥If you’d like to retain transform styles while allowing transform animations, create a wrapper, where the outermost node is the positioned one, and the inner is the actual styled element.

自定义位置样式

¥Custom position styles

如果 floatingStyles 不适合完全定制,则可组合项会直接返回坐标和定位策略。

¥The composable returns the coordinates and positioning strategy directly if floatingStyles is not suitable for full customization.

const {x, y, strategy} = useFloating(reference, floating);

返回值

¥Return value

可组合的 返回 computePosition 中的所有值,加上一些与 Vue 配合使用的额外功能。这包括有关最终放置的数据和渲染时有用的中间件数据。

¥The composable returns all the values from computePosition, plus some extras to work with Vue. This includes data about the final placement and middleware data which are useful when rendering.

选项

¥Options

可组合项接受所有 computePosition 的选项,这允许你自定义位置。这是一个例子:

¥The composable accepts all the options from computePosition, which allows you to customize the position. Here’s an example:

import {
  useFloating,
  offset,
  flip,
  shift,
} from '@floating-ui/vue';
 
// Inside your component
useFloating(reference, floating, {
  placement: 'right',
  middleware: [offset(10), flip(), shift()],
});

该可组合项还接受 Ref 选项:

¥The composable also accepts Ref options:

import {
  useFloating,
  offset,
  flip,
  shift,
} from '@floating-ui/vue';
 
// Inside your component
const placement = ref('right');
const middleware = ref([offset(10), flip(), shift()]);
useFloating(reference, floating, {
  placement,
  middleware,
});

中间件 可以改变基本 placement 的定位,充当可见性优化器,或者提供数据以供使用。

¥Middleware can alter the positioning from the basic placement, act as visibility optimizers, or provide data to use.

已传递的中间件的文档可在此处找到:

¥The docs for the middleware that were passed are available here:

锚定

¥Anchoring

该位置仅在渲染时计算一次,或者当 referencefloating 元素更改时计算 - 例如,通过条件渲染安装浮动元素。

¥The position is only calculated once on render, or when the reference or floating elements changed — for example, the floating element get mounted via conditional rendering.

为了确保浮动元素在各种情况下保持锚定到其参考元素而不分离(例如滚动或调整页面大小时),你可以将 autoUpdate 实用程序传递给 whileElementsMounted 属性:

¥To ensure the floating element remains anchored to its reference element in a variety of scenarios without detaching — such as when scrolling or resizing the page — you can pass the autoUpdate utility to the whileElementsMounted prop:

import {useFloating, autoUpdate} from '@floating-ui/vue';
 
// Inside your component
useFloating(reference, floating, {
  whileElementsMounted: autoUpdate,
});

将选项传递给 autoUpdate

¥To pass options to autoUpdate:

useFloating(reference, floating, {
  whileElementsMounted(...args) {
    const cleanup = autoUpdate(...args, {animationFrame: true});
    // Important! Always return the cleanup function.
    return cleanup;
  },
});

确保你对浮动元素使用条件渲染 (v-if),而不是不透明度/可见性/显示样式。如果你使用 v-show,请避免使用 whileElementsMounted 属性。

¥Ensure you are using conditional rendering (v-if) for the floating element, not an opacity/visibility/display style. If you are using v-show instead, avoid the whileElementsMounted prop.

手动更新

¥Manual updating

虽然 autoUpdate 涵盖了必须更新浮动元素位置的大多数情况,但由于性能/平台限制,它并未涵盖所有可能的情况。

¥While autoUpdate covers most cases where the position of the floating element must be updated, it does not cover every single one possible due to performance/platform limitations.

该可组合项返回一个 update() 函数来随意更新位置:

¥The composable returns an update() function to update the position at will:

<script setup>
const {update} = useFloating(reference, floating);
</script>
 
<template>
  <Panel @resize="update" />
</template>

定制组件

¥Custom components

该可组合项还接受自定义组件模板引用:

¥The composable also accepts custom component template refs:

<script setup>
import {ref} from 'vue';
import {useFloating} from '@floating-ui/vue';
 
import MyButton from './MyButton.vue';
import MyTooltip from './MyTooltip.vue';
 
const reference = ref(null);
const floating = ref(null);
const {floatingStyles} = useFloating(reference, floating);
</script>
 
<template>
  <MyButton ref="reference">Button</MyButton>
  <MyTooltip ref="floating">Tooltip</MyTooltip>
</template>

效果

¥Effects

定位是在异步函数中完成的,这意味着在执行布局效果之后,在微任务期间位置已准备好。这意味着最初,浮动元素位于其偏移容器的左上角 (0, 0) — 因此调用会导致滚动等副作用的 DOM 方法将导致意外行为。

¥Positioning is done in an async function, which means the position is ready during a microtask, after layout effects are executed. This means initially, the floating element is situated at the top-left (0, 0) of its offset container — so calling DOM methods that cause side-effects like scrolling will result in unexpected behavior.

该可组合项返回一个 isPositioned 布尔引用,让你知道浮动元素是否已定位:

¥The composable returns an isPositioned boolean ref that lets you know if the floating element has been positioned:

const open = ref(false);
const {isPositioned} = useFloating(reference, floating, {
  // Synchronize `isPositioned` with an `open` ref.
  open,
});
 
// Each time the floating element opens, we want to focus and
// scroll some element into view.
watch(isPositioned, (isPositioned) => {
  if (isPositioned) {
    someElement.focus();
    someElement.scrollIntoView();
  }
});

open 选项接受表示浮动元素的打开/关闭状态的布尔引用。这确保你可以在主机组件未卸载时每次打开时等待,这在引用元素在页面上重新定位的情况下是必要的。

¥The open option accepts a boolean ref that represents the open/close state of the floating element. This ensures you can wait each time it opens when the host component does not unmount, which is necessary in cases where the reference element relocates on the page.

箭头

¥Arrow

从该包导出的 arrow 模块除了元素之外还允许模板引用。详情请参见 arrow

¥The arrow module exported from this package allows template refs in addition to elements. See arrow for details.

<script setup>
import {arrow, useFloating} from '@floating-ui/vue';
import {ref} from 'vue';
 
const reference = ref(null);
const floating = ref(null);
const floatingArrow = ref(null);
 
const {floatingStyles, middlewareData} = useFloating(
  reference,
  floating,
  {
    middleware: [arrow({element: floatingArrow})],
  },
);
</script>
 
<template>
  <span ref="reference">Reference</span>
  <div ref="floating" :style="floatingStyles">
    Floating
    <div
      ref="floatingArrow"
      :style="{
        position: 'absolute',
        left:
          middlewareData.arrow?.x != null
            ? `${middlewareData.arrow.x}px`
            : '',
        top:
          middlewareData.arrow?.y != null
            ? `${middlewareData.arrow.y}px`
            : '',
      }"
    ></div>
  </div>
</template>

虚拟元素

¥Virtual Element

详情请参见 虚拟元素。示例:

¥See Virtual Elements for details. Example:

<script setup>
import {onMounted, ref} from 'vue';
import {useFloating} from '@floating-ui/vue';
 
const reference = ref(null);
const floating = ref(null);
const {floatingStyles} = useFloating(reference, floating);
 
onMounted(() => {
  /**
 
   * Assign the virtual element to reference inside
 
   * a lifecycle hook or effect or event handler.
   */
  reference.value = {
    getBoundingClientRect() {
      return {
        // ...
      };
    },
  };
});
</script>
 
<template>
  <div ref="floating">Tooltip</div>
</template>