# useOverflow

## 使用方法

在屏幕外的那块隐藏容器里把所有子项都排一遍，量出当前宽度能放下几项，这样切换时不会闪。容器和子项尺寸变化都用 ResizeObserver 盯着。测量容器里按顺序放全部项，最后可以再放一个溢出指示器，给它标上 `data-overflow-indicator`。

这块测量容器画在看不见的地方，所以每一项都还是真实宽度。给它加上 `inert`，它就不会进键盘顺序，也不会被读屏读到。看得见的容器只渲染 `visibleCount` 项，再自己放一个溢出提示，这个提示不参与测量。

这两个容器在这里都是模板 ref，用 `ref` 绑上去就行。`visibleCount`、`rows`、`rowHeight` 都是 ref，可以直接拿去渲染；想立刻重量一次就调 `remeasure()`。

```ts
import { useOverflow } from '@astryx-vue/core'
```

```vue
<script setup lang="ts">
import { useOverflow } from '@astryx-vue/core'

const items = ['一', '二', '三', '四', '五']
const { containerRef, hasOverflow, measureRef, visibleCount } = useOverflow(items.length, { gap: 8 })
</script>

<template>
  <div ref="containerRef" class="row">
    <button v-for="item in items.slice(0, visibleCount)" :key="item">
      {{ item }}
    </button>
    <button v-if="hasOverflow">
      +{{ items.length - visibleCount }} 更多
    </button>
  </div>

  <div ref="measureRef" class="row" inert>
    <button v-for="item in items" :key="item">
      {{ item }}
    </button>
    <button data-overflow-indicator>
      +{{ items.length }} 更多
    </button>
  </div>
</template>
```

## 建议

| 指引 | 做法 |
| --- | --- |
| Do | 全部项都渲染进 `measureRef` 那块隐藏容器，只有前 `visibleCount` 项渲染进 `containerRef` 那块看得见的容器。 |
| Do | 测量容器最后放一个溢出指示器（比如「+N 更多」按钮），并给它标上 `data-overflow-indicator`。 |
| Don't | 拿它量竖向溢出，这个函数只量横向宽度。 |

## 参数

| 参数 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| `itemCount` | `MaybeRefOrGetter<number>` | — | 要测量的项数。 |
| `options` | `UseOverflowOptions` | — | 溢出行为的配置。 |
| `options.gap` | `number` | `0` | 项与项的间距，单位像素，参与宽度计算。 |
| `options.minVisibleItems` | `number` | `0` | 哪怕挤不下也至少显示的项数。 |
| `options.maxVisibleItems` | `number` | — | 哪怕都挤得下也不能超过的项数。下限比它大时，下限胜出。 |
| `options.maxRows` | `number` | — | 最多排几行，剩下的收进指示器。不传或传 `1` 只排一行。 |
| `options.collapseFrom` | `'start' \| 'end'` | `'end'` | 从哪一头开始收起。 |
| `options.behavior` | `'observeParent' \| 'observeSelf'` | `'observeSelf'` | 量哪一个元素的宽度。`observeParent` 量父元素的内容宽度，看得见的容器本身可以继续跟着内容收缩。 |

## 返回值

| 名称 | 类型 | 说明 |
| --- | --- | --- |
| `containerRef` | `Ref` | 绑到看得见的容器上。 |
| `measureRef` | `Ref` | 绑到屏幕外的测量容器上，里面放全部项。 |
| `visibleCount` | `Ref<number>` | 看得见的容器里能放下几项。 |
| `hasOverflow` | `ComputedRef<boolean>` | 是不是有项被收起来了（`visibleCount < itemCount`）。 |
| `rows` | `Ref<number>` | 看得见的项占几行。单行模式是 `1`，什么都没显示时是 `0`。 |
| `rowHeight` | `Ref<number>` | 量到的最大项高，多行容器用它定高度。 |
| `remeasure` | `() => void` | 再量一次。测试里改过宽度、或者折叠状态变了之后用得上。 |

## 元素版

`useOverflow(element, isActive)` 是另一个签名。它不量一排项，只量一个盒子：判断这个元素里的内容是不是比它自己的可视区域高，返回一个 `Ref<boolean>`。`isActive` 为 false 时它不做测量。

| 名称 | 类型 | 说明 |
| --- | --- | --- |
| `element` | `Ref` | 要量的那个盒子的模板 ref。 |
| `isActive` | `Ref<boolean>` | 要不要量。为 false 时结果一直是 `false`。 |
| `返回值` | `Ref<boolean>` | 内容是不是比盒子高。 |
