vue3 +TS 如何实现 元素div 内有10个子元素,一行展示横向滚动条,当依次往右点击子元素时,被点击元素的上一个不在可视区域,则自动横向滚动滚动条,把上一个元素滑到可视区域,如果依次向左点子元素时,被点击元素后一个如果不在可视区域,则自动横向滚动,把他左边的临近元素滚动到可视区域
时间: 2024-03-17 14:43:51 浏览: 263
可以使用Vue3的Composition API和Ref来实现这个功能。以下是一个示例代码:
```typescript
<template>
<div class="container" ref="container">
<div class="wrapper" ref="wrapper">
<div v-for="(item, index) in items" :key="index" class="item" ref="items[index]">
{{ item }}
</div>
</div>
</div>
</template>
<script lang="ts">
import { onMounted, reactive, ref } from 'vue'
export default {
setup() {
const container = ref<HTMLElement | null>(null)
const wrapper = ref<HTMLElement | null>(null)
const items = reactive(['1', '2', '3', '4', '5', '6', '7', '8', '9', '10'])
const itemRefs = reactive<Record<string, HTMLElement | null>>({})
onMounted(() => {
// 计算一行能展示的元素数量
const containerWidth = container.value ? container.value.offsetWidth : 0
const itemWidth = itemRefs['0'] ? itemRefs['0'].offsetWidth : 0
const itemsPerRow = Math.floor(containerWidth / itemWidth)
// 计算总共需要展示几行
const rowCount = Math.ceil(items.length / itemsPerRow)
// 设置Wrapper的宽度,使得可以横向滚动
if (wrapper.value) {
wrapper.value.style.width = `${items.length * itemWidth}px`
}
// 点击事件
const handleClick = (index: number) => {
// 计算当前元素所在的行数和列数
const row = Math.floor(index / itemsPerRow)
const col = index % itemsPerRow
// 判断点击的元素是否在可视范围内
const containerRect = container.value ? container.value.getBoundingClientRect() : null
const itemRect = itemRefs[`${index}`] ? itemRefs[`${index}`].getBoundingClientRect() : null
if (containerRect && itemRect) {
if (itemRect.left < containerRect.left) {
// 如果点击的元素在可视范围左侧,则滚动到左侧
if (wrapper.value) {
wrapper.value.scrollLeft -= (containerRect.left - itemRect.left)
}
} else if (itemRect.right > containerRect.right) {
// 如果点击的元素在可视范围右侧,则滚动到右侧
if (wrapper.value) {
wrapper.value.scrollLeft += (itemRect.right - containerRect.right)
}
}
}
}
// 将点击事件绑定到每个元素上
for (let i = 0; i < items.length; i++) {
const itemRef = itemRefs[`${i}`]
if (itemRef) {
itemRef.addEventListener('click', () => handleClick(i))
}
}
})
return {
container,
wrapper,
items,
itemRefs,
}
},
}
</script>
<style scoped>
.container {
width: 300px;
height: 100px;
overflow-x: scroll;
white-space: nowrap;
}
.wrapper {
display: inline-block;
}
.item {
display: inline-block;
width: 80px;
height: 80px;
margin-right: 10px;
background-color: #ccc;
}
</style>
```
在这个示例代码中,我们首先通过`ref`获取到了容器元素和包裹元素的引用,然后使用`reactive`创建了一个可以响应式更新的数组来存储子元素的数据。接着,在`onMounted`钩子中,我们计算了一行能够展示的元素数量,以及总共需要展示几行,然后设置了Wrapper的宽度,使得可以横向滚动。最后,我们将点击事件绑定到每个元素上,并在点击事件中判断点击的元素是否在可视范围内,如果不在,则滚动滚动条将其滚动到可视范围内。
阅读全文