vue3项目自己封装的电梯导航组件,快速的实现页面滚动导航
一、实现思路
电梯导航主要是要实现两个功能点:
1. 点击导航滚动页面到指定位置
2. 滚动到页面的位置实现导航的动态更新
使用技术:
1. 实现1功能使用的js的scrollInfoView语法,让指定元素调用这个方法可以滚动到视图区
2. 2功能的实现用到了js的IntersectionObserver这个api,通过监听目标元素滚动到视图区的时机,然后实现自己的功能,具体用法可以到MDN上查看。
预览地址: static-mp-7dd8d74a-436d-4c1e-a81d-218c2904f2ae.next.bspapp.com/index.htmlh…
二、组件封装
<template>
<ul
class="nav-list"
:style="{
width: width + 'px',
...position,
}"
>
<li
:class="['nav-list-item', activeIndex == index + 1 ? 'active' : '']"
v-for="(item, index) in list"
:key="index"
@click="changeHandle(index)"
>
{{ item.label }}
</li>
</ul>
</template>
<script setup>
import { reactive, ref, onMounted, toRefs } from "vue"
const props = defineProps({
position: {
type: Object,
default: {
left: "20px",
top: "20px",
},
},
width: {
type: Number,
default: 120,
},
activeColor: {
type: String,
default: "#00b393",
},
list: {
type: Array,
default: [{}],
},
})
const { list } = toRefs(props)
const activeIndex = ref(1)
function changeHandle(index) {
activeIndex.value = index + 1
// 让对应的元素滚动到视图区
document.getElementById(list.value[index].elId)?.scrollIntoView({
behavior: "smooth",
})
}
function changeActive(els) {
console.log(els)
if (els[0].isIntersecting) {
let index = list.value.findIndex(
(item) => item.elId == els[0].target.id
)
if (index != -1) {
activeIndex.value = index + 1
}
}
}
onMounted(() => {
let observer = new IntersectionObserver(changeActive, {
root: null,
threshold: 0.1,
})
list.value.map((item) => {
let el = document.getElementById(item.elId)
el && observer.observe(el)
})
})
</script>
<style lang="less" scoped>
.nav-list {
position: fixed;
background-color: #fff;
box-shadow: 0 4px 12px 0 rgba(0, 0, 0, 0.12);
padding: 10px 0;
border-radius: 10px;
.nav-list-item {
padding: 10px;
text-align: center;
background-color: #fff;
font-size: 16px;
color: #333;
cursor: pointer;
border-radius: 3px;
list-style: none;
transition: all 0.2s ease;
&.active {
background-color: v-bind(activeColor);
color: #fff;
}
}
}
</style>
三、组件使用
<script setup>
import { reactive } from "vue"
import NavList from "./components/navList.vue"
const navList = reactive([
{
label: "一层",
elId: "el1",
},
{
label: "二层",
elId: "el2",
},
{
label: "三层",
elId: "el3",
},
{
label: "四层",
elId: "el4",
},
{
label: "五层",
elId: "el5",
},
])
</script>
<template>
<NavList :list="navList" :position="{ bottom: '20px', right: '20px' }" />
<div id="el1" class="el-item">元素一</div>
<div id="el2" class="el-item">元素2</div>
<div id="el3" class="el-item">元素3</div>
<div id="el4" class="el-item">元素4</div>
<div id="el5" class="el-item">元素5</div>
</template>
<style scoped>
.el-item {
height: 800px;
font-size: 30px;
}
</style>
浙公网安备 33010602011771号