介绍
实时告知当前处于屏幕中的锚点,或者滚动到指定锚点位置。
代码演示
基础使用
ScrollSpy 组件内部使用可滚动元素容器,需要设置固定的高度。 ScrollSpyAnchor 是用作定位的锚点,需要设置 name 属性,且其值必须唯一。
使用 v-model 绑定当前的锚点。
vue
<template>
<div>当前 anchor: {{ current }}</div>
<s-button style="margin: 5px 0" @click="current = '120000'">设置当前 anchor 为: 120000</s-button>
<s-scroll-spy v-model="current" style="height: 200px; border: 1px solid var(--s-border-color)">
<template v-for="item in listData" :key="item.code">
<s-scroll-spy-anchor :name="item.code" />
<div class="sticky top-0 p-1 bg-(--s-bg-color-container)">{{ item.code }}</div>
<div class="flex justify-center items-center h-48 m-2 bg-(--s-fill-color-secondary)">
{{ item.name }}
</div>
</template>
</s-scroll-spy>
</template>
<script setup lang="ts">
import { getProvinces } from '@/api'
import { onMounted, ref } from 'vue'
const current = ref('110000')
const listData = ref<{ code: string; name: string }[]>([])
onMounted(async () => {
listData.value = (await getProvinces()).list
})
</script>vue
<template>
<div>当前 anchor: {{ current }}</div>
<s-button style="margin: 5px 0" @click="current = '120000'">设置当前 anchor 为: 120000</s-button>
<s-scroll-spy v-model="current" style="height: 200px; border: 1px solid var(--s-border-color)">
<template v-for="item in listData" :key="item.code">
<s-scroll-spy-anchor :name="item.code" />
<div class="sticky top-0 p-1 bg-(--s-bg-color-container)">{{ item.code }}</div>
<div class="flex justify-center items-center h-48 m-2 bg-(--s-fill-color-secondary)">
{{ item.name }}
</div>
</template>
</s-scroll-spy>
</template>
<script setup lang="js">
import { getProvinces } from '@/api'
import { onMounted, ref } from 'vue'
const current = ref('110000')
const listData = ref([])
onMounted(async () => {
listData.value = (await getProvinces()).list
})
</script>动态更新
如果锚点的位置有变动,或者新增/删除了锚点,需要调用 update 方法重新计算锚点位置。
vue
<template>
<div>当前 anchor: {{ value }}</div>
<s-button style="margin: 5px 0" @click="value = '120100'">设置当前 anchor 为: 120100</s-button>
<s-scroll-spy v-model="value" style="height: 200px; border: 1px solid var(--s-border-color)">
<template v-for="item in listData" :key="item.code">
<s-scroll-spy-anchor :name="item.code" />
<div class="sticky top-0 p-1 bg-(--s-bg-color-container)">{{ item.code }}</div>
<div class="flex justify-center items-center h-20 m-2 bg-(--s-fill-color-secondary)">
{{ item.name }}
</div>
</template>
<s-load-more :status="status" @load="getData" />
</s-scroll-spy>
</template>
<script setup lang="ts">
import { LoadMoreStatus } from 'sard'
import { ref } from 'vue'
import { getCities } from '@/api'
const value = ref('110000')
const listData = ref<{ code: string; name: string }[]>([])
const status = ref<LoadMoreStatus>(LoadMoreStatus.INCOMPLETE)
let page = 1
const getData = async () => {
status.value = LoadMoreStatus.LOADING
return getCities({ page })
.then(({ list, total }) => {
listData.value = page === 1 ? list : [...listData.value, ...list]
if (listData.value.length >= total || list.length === 0) {
status.value = LoadMoreStatus.COMPLETE
} else {
status.value = LoadMoreStatus.INCOMPLETE
page++
}
})
.catch(() => {
status.value = LoadMoreStatus.ERROR
})
}
</script>vue
<template>
<div>当前 anchor: {{ value }}</div>
<s-button style="margin: 5px 0" @click="value = '120100'">设置当前 anchor 为: 120100</s-button>
<s-scroll-spy v-model="value" style="height: 200px; border: 1px solid var(--s-border-color)">
<template v-for="item in listData" :key="item.code">
<s-scroll-spy-anchor :name="item.code" />
<div class="sticky top-0 p-1 bg-(--s-bg-color-container)">{{ item.code }}</div>
<div class="flex justify-center items-center h-20 m-2 bg-(--s-fill-color-secondary)">
{{ item.name }}
</div>
</template>
<s-load-more :status="status" @load="getData" />
</s-scroll-spy>
</template>
<script setup lang="js">
import { LoadMoreStatus } from 'sard'
import { ref } from 'vue'
import { getCities } from '@/api'
const value = ref('110000')
const listData = ref([])
const status = ref(LoadMoreStatus.INCOMPLETE)
let page = 1
const getData = async () => {
status.value = LoadMoreStatus.LOADING
return getCities({ page })
.then(({ list, total }) => {
listData.value = page === 1 ? list : [...listData.value, ...list]
if (listData.value.length >= total || list.length === 0) {
status.value = LoadMoreStatus.COMPLETE
} else {
status.value = LoadMoreStatus.INCOMPLETE
page++
}
})
.catch(() => {
status.value = LoadMoreStatus.ERROR
})
}
</script>API
ScrollSpyProps
| 属性 | 描述 | 类型 | 默认值 |
|---|---|---|---|
| model-value | 当前绑定锚点名称 | string | number | - |
| offset | 锚点距离顶部的偏移量 | number | 0 |
| upper-threshold | 距顶部/左边多远时(单位 px),触发 scrolltoupper 事件 | number | string | 50 |
| lower-threshold | 距底部/右边多远时(单位 px),触发 scrolltolower 事件 | number | string | 50 |
| disabled | 是否禁用,禁用时无法滚动 | boolean | false |
ScrollSpySlots
| 插槽 | 描述 | 属性 |
|---|---|---|
| default | 自定义默认内容 | - |
ScrollSpyEmits
| 事件 | 描述 | 类型 |
|---|---|---|
| update:modelValue | 当前锚点改变时触发 | (name: number | string) => void |
| change | 当前锚点改变时触发 | (name: number | string) => void |
ScrollSpyExpose
| 属性 | 描述 | 类型 |
|---|---|---|
| update | 更新锚点位置 | () => void |