示例
功能描述
- 点击左侧导航栏,右侧能滚动到指定的位置
- 右侧滚动,左侧能自动选中
存在问题
优化版本链接
使用
这儿是结合element-ui 一起使用的,同学们使用的时候要注意引入对应组件
<template>
<div class="container pr flex-wrap">
<el-menu
:default-active="state.defaultActive"
class="el-menu-vertical-demo width-120"
>
<el-menu-item
:index="item.id"
v-for="item in state.menuList"
:key="item.id"
@click="changenavigationBar(item.id)"
>
<span>{{ item.title }}</span>
</el-menu-item>
</el-menu>
<div class="content">
<h2>我是右侧的顶部内容</h2>
<!-- 必传项为 id id必须和el-menu-item的index一致,activeId函数用于接收滚动到那个id区域了-->
<kl-anchor
class="content-item"
:id="item.id"
v-for="item in state.menuList"
:key="item.id"
@activeId="activeId"
>
{{ item.id }}
</kl-anchor>
</div>
</div>
</template>
<script lang="ts" setup>
import { reactive } from "vue-demi";
const state = reactive({
defaultActive: "nav1",
menuList: [
{
id: "nav1",
title: "nav11",
},
{
id: "nav2",
title: "nav22",
},
{
id: "nav3",
title: "nav33",
},
{
id: "nav4",
title: "nav44",
},
{
id: "nav5",
title: "nav55",
},
{
id: "nav6",
title: "nav66",
},
],
});
const activeId = (id: string) => {
if (id !== state.defaultActive) {
state.defaultActive = id;
}
};
const changenavigationBar = (id: String) => {
var PageId = document.querySelector("#" + id) as HTMLElement;
window.scrollTo({
top: PageId.offsetTop,
behavior: "smooth",
});
};
</script>
<style lang="scss" scoped>
.width-120 {
width: 120px;
}
.content-item {
height: 500px;
}
.el-menu-vertical-demo {
position: fixed;
top: 0;
left: 0;
}
.container {
padding-left: 120px;
}
</style>
实现
kl-anchor
<template>
<div class="kl-anchor" :id="id">
<slot> </slot>
</div>
</template>
<script lang="ts" setup>
import {
onBeforeUnmount,
onMounted,
reactive,
onBeforeUpdate,
nextTick,
} from "vue-demi";
const props = defineProps({
id: {
type: String,
required: true,
},
accuracy: {
type: Number,
default: 150,
},
});
const emits = defineEmits(["activeId"]);
interface i_state {
el: HTMLElement | null;
offsetTop: number;
clientHeight: number;
myHeight: number;
}
const state: i_state = reactive({
el: null,
offsetTop: 0,
clientHeight: 0,
myHeight: 0,
});
function throttle(fn: () => void, delay: number) {
let time1 = 0;
return function () {
let time2 = Date.now();
if (time2 - time1 >= delay) {
fn();
time1 = time2;
}
};
}
const eventScroll = throttle(() => {
let bodyScroll: number = document.documentElement.scrollTop;
if (
bodyScroll - state.offsetTop >= 0 &&
state.offsetTop + state.myHeight > bodyScroll
) {
emits("activeId", props.id);
}
}, props.accuracy);
function handleEvent() {
state.el = document.querySelector("#" + props.id) as HTMLElement;
state.myHeight = state.el.offsetHeight;
state.offsetTop = state.el.offsetTop;
state.clientHeight = document.body.clientHeight;
window.document.addEventListener("scroll", eventScroll);
}
onMounted(() => {
handleEvent();
});
onBeforeUpdate(() => {
nextTick(() => {
handleEvent();
});
});
onBeforeUnmount(() => {
window.document.removeEventListener("scroll", eventScroll);
});
</script>
<style lang="scss" scoped></style>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)