锚点滚动有几个基本要素:
1、父级盒子
2、子级元素
3、锚点
在一个实际场景里,通常是父级盒子内部套了一个子元素列表,父级盒子有一个指定高度,子元素高度超过父级盒子时,子元素在父元素内部滚动。
在布局方面,左侧和右侧没有任何关联,左侧仅仅只是分类列表,右侧仅仅只是分类详情列表,根据这个可以得出如下布局:
点击左侧分类的时候,通过事件,获取右侧分类锚点,然后给右侧的父级盒子设置滚动
下面是完整代码,非常简单:
<template>
<view style="display: flex;">
<view class="left_box">
<view class="left_inner_box" :class="current == item.value ? 'current' : ''" v-for="item in list"
:key="item.value" @click="onTab(item.value)">
{{item.label}}
</view>
</view>
<view class="right_box">
<!-- 给子元素设置锚点id -->
<view style="background: #3c3f47;" id="step1">
<view class="right_inner_box" v-for="item in listInfo.type1">
{{ item.label }}
</view>
</view>
<!-- 给子元素设置锚点id -->
<view style="background: green;" id="step2">
<view class="right_inner_box" v-for="item in listInfo.type2">
{{ item.label }}
</view>
</view>
<view style="background: #3c3f47;" id="step3">
<view class="right_inner_box" v-for="item in listInfo.type3">
{{ item.label }}
</view>
</view>
<view style="background: green;" id="step4">
<view class="right_inner_box" v-for="item in listInfo.type4">
{{ item.label }}
</view>
</view>
<view style="background: #3c3f47;" id="step5">
<view class="right_inner_box" v-for="item in listInfo.type5">
{{ item.label }}
</view>
</view>
<view style="background: green;" id="step6">
<view class="right_inner_box" v-for="item in listInfo.type6">
{{ item.label }}
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
list: [{
label: '分类一',
value: 1
},
{
label: '分类二',
value: 2
},
{
label: '分类三',
value: 3
},
{
label: '分类四',
value: 4
},
{
label: '分类五',
value: 5
},
{
label: '分类六',
value: 6
}
],
current: 1,
listInfo: {
type1: [{
label: '分类一的内容-01',
value: 11
},
{
label: '分类一的内容-02',
value: 12
},
{
label: '分类一的内容-03',
value: 13
},
{
label: '分类一的内容-04',
value: 14
},
{
label: '分类一的内容-05',
value: 15
},
{
label: '分类一的内容-06',
value: 16
},
{
label: '分类一的内容-07',
value: 17
},
],
type2: [{
label: '分类二的内容-01',
value: 21
},
{
label: '分类二的内容-02',
value: 22
},
{
label: '分类二的内容-03',
value: 23
},
{
label: '分类二的内容-04',
value: 24
},
{
label: '分类二的内容-05',
value: 25
},
{
label: '分类二的内容-06',
value: 26
},
{
label: '分类二的内容-07',
value: 27
},
],
type3: [{
label: '分类三的内容-01',
value: 31
},
{
label: '分类三的内容-02',
value: 32
},
{
label: '分类三的内容-03',
value: 33
},
{
label: '分类三的内容-04',
value: 34
},
{
label: '分类三的内容-05',
value: 35
},
{
label: '分类三的内容-06',
value: 36
},
{
label: '分类三的内容-07',
value: 37
},
],
type4: [{
label: '分类四的内容-01',
value: 41
},
{
label: '分类四的内容-02',
value: 42
},
{
label: '分类四的内容-03',
value: 43
},
{
label: '分类四的内容-04',
value: 44
},
{
label: '分类四的内容-05',
value: 45
},
{
label: '分类四的内容-06',
value: 46
},
{
label: '分类四的内容-07',
value: 47
},
],
type5: [{
label: '分类五的内容-01',
value: 51
},
{
label: '分类五的内容-02',
value: 52
},
{
label: '分类五的内容-03',
value: 53
},
{
label: '分类五的内容-04',
value: 54
},
{
label: '分类五的内容-05',
value: 55
},
{
label: '分类五的内容-06',
value: 56
},
{
label: '分类五的内容-07',
value: 57
},
],
type6: [{
label: '分类六的内容-01',
value: 61
},
{
label: '分类六的内容-02',
value: 62
},
{
label: '分类六的内容-03',
value: 63
},
{
label: '分类六的内容-04',
value: 64
},
{
label: '分类六的内容-05',
value: 65
},
{
label: '分类六的内容-06',
value: 66
},
{
label: '分类六的内容-07',
value: 67
},
]
}
};
},
methods: {
onTab(value) {
this.current = value;
const dom = document.getElementById(`step${value}`);
if (dom) {
dom.scrollIntoView({
behavior: 'smooth',
block: 'center'
});
}
},
}
}
</script>
<style lang="scss" scoped>
.left_box {
width: 100px;
.left_inner_box {
width: 100px;
height: 40px;
line-height: 40px;
text-align: center;
background-color: #ccc;
margin-bottom: 10px;
}
.current {
color: red;
background-color: cyan;
}
}
.right_box {
width: calc(100% - 110px);
height: 600px;
border: 1px solid red;
overflow: scroll;
.right_inner_box {
height: 40px;
line-height: 40px;
text-align: center;
color: #fff;
margin-bottom: 4px;
}
}
</style>
上面的代码很简单,就是通过点击分类,获取右侧的锚点id,然后给该锚点的父级盒子设置滚动,滚动到指定位置。
核心代码就是这个:
onTab(value) {
this.current = value;
// 根据锚点id获取dom元素
const dom = document.getElementById(`step${value}`);
if (dom) {
// 给该元素的父级盒子设置滚动
dom.scrollIntoView({
behavior: 'smooth',
block: 'center'
});
}
},
scrollIntoView这个事件,可以越级滚动,那怕子元素不是滚动盒子的直属子元素,在子元素外层嵌套了多个父盒子,照样能让最外层的父级滚动盒子滚动到指定锚点位置,如下:
<template>
<view style="display: flex;">
<view class="left_box">
<view class="left_inner_box" :class="current == item.value ? 'current' : ''" v-for="item in list"
:key="item.value" @click="onTab(item.value)">
{{item.label}}
</view>
</view>
<!-- 父级滚动盒子 -->
<view class="right_box">
<!-- 嵌套层级一 -->
<view>
<!-- 嵌套层级二 -->
<view>
<!-- 嵌套层级三 -->
<view style="background: #3c3f47;" id="step1">
<view class="right_inner_box" v-for="item in listInfo.type1">
{{ item.label }}
</view>
</view>
</view>
</view>
<view>
<view>
<view style="background: green;" id="step2">
<view class="right_inner_box" v-for="item in listInfo.type2">
{{ item.label }}
</view>
</view>
</view>
</view>
<view>
<view>
<view style="background: #3c3f47;" id="step3">
<view class="right_inner_box" v-for="item in listInfo.type3">
{{ item.label }}
</view>
</view>
</view>
</view>
<view>
<view>
<view style="background: green;" id="step4">
<view class="right_inner_box" v-for="item in listInfo.type4">
{{ item.label }}
</view>
</view>
</view>
</view>
<view>
<view>
<view style="background: #3c3f47;" id="step5">
<view class="right_inner_box" v-for="item in listInfo.type5">
{{ item.label }}
</view>
</view>
</view>
</view>
<view>
<view>
<view style="background: green;" id="step6">
<view class="right_inner_box" v-for="item in listInfo.type6">
{{ item.label }}
</view>
</view>
</view>
</view>
</view>
</view>
</template>
需要注意的:
1、scrollIntoView的behavior: 'smooth'属性不兼容低版本浏览器,例如IE
2、js也可以设置平滑滚动效果: dom.style.scrollBehavior = "smooth"
3、子元素需要设置锚点id
4、scrollIntoView的滚动效果不受嵌套层级影响
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。