Skip to content

Commit d953b14

Browse files
committed
refactor:抽取悬浮菜单组件
1 parent 35443c1 commit d953b14

File tree

2 files changed

+100
-20
lines changed

2 files changed

+100
-20
lines changed

Diff for: src/components/common/FloatMenu.vue

+91
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
<template>
2+
<ul id="menu">
3+
<li
4+
v-for="(item, index) in menuItems"
5+
:key="index"
6+
:title="item.name"
7+
:class="item.name === activeTitle ? 'active' : ''"
8+
@click.stop="onMenuClick(item, index)"
9+
>
10+
{{ item.name }}
11+
</li>
12+
</ul>
13+
</template>
14+
15+
<script setup>
16+
import { ref } from 'vue'
17+
18+
const props = defineProps({
19+
menuItems: {
20+
type: Array,
21+
required: true
22+
},
23+
headerOffset: {
24+
type: Number,
25+
default: 45
26+
}
27+
})
28+
29+
const emit = defineEmits(['menuClick'])
30+
31+
const activeTitle = ref(null)
32+
33+
// 滚动到指定部分
34+
const onMenuClick = (item, index) => {
35+
activeTitle.value = item.name
36+
37+
if(item.id) {
38+
const element = document.querySelector(item.id)
39+
if(element) {
40+
const elementPosition = element.getBoundingClientRect().top
41+
const offsetPosition = elementPosition + window.pageYOffset - props.headerOffset
42+
43+
window.scrollTo({
44+
top: offsetPosition,
45+
behavior: "smooth"
46+
})
47+
}
48+
}
49+
50+
emit('menuClick', item, index)
51+
}
52+
</script>
53+
54+
<style lang="scss" scoped>
55+
#menu {
56+
position: fixed;
57+
left: 0;
58+
top: 50%;
59+
width: 120px;
60+
transform: translateY(-50%);
61+
background-color: #fff;
62+
box-shadow: 0 4px 8px 0 rgba(7, 17, 27, .1);
63+
border-radius: 0 8px 8px 0;
64+
text-align: center;
65+
color: #6d7278;
66+
z-index: 3;
67+
user-select: none;
68+
}
69+
70+
#menu li {
71+
position: relative;
72+
padding: 16px 0;
73+
cursor: pointer;
74+
transition: color .2s;
75+
}
76+
77+
#menu li.active,
78+
#menu li:hover {
79+
color: #e02020;
80+
}
81+
82+
#menu li+li::after {
83+
position: absolute;
84+
top: 0;
85+
left: 50%;
86+
margin-left: -30px;
87+
content: '';
88+
width: 60px;
89+
border: 1px solid #f3f5f7;
90+
}
91+
</style>

Diff for: src/views/course.vue

+9-20
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
<template>
22
<div class="main">
3-
<ul id="menu">
4-
<li :title="item.name" v-for="(item, index) in menuData" :key="index" @click.stop="rollTo(item, index)"
5-
:class="item.name === heightTitle ? 'active' : ''">
6-
{{ item.name }}
7-
</li>
8-
</ul>
3+
<FloatMenu
4+
:menuItems="menuData"
5+
@menuClick="onMenuClick"
6+
/>
97

108
<!-- 学习路线 -->
119
<div class="bg000" id="roadMap">
@@ -40,6 +38,7 @@
4038

4139
<script setup>
4240
import { onMounted, ref } from "vue";
41+
import FloatMenu from "@/components/common/FloatMenu.vue";
4342
import CourseList from "./CourseList.vue";
4443
import study from "./home/study.vue";
4544
import { getCarouselData, getCourseList } from "@/api/videoCourse";
@@ -55,20 +54,10 @@ const heightTitle = ref(null);
5554
const courses = ref([]);
5655
const courseResp = ref([]);
5756
58-
59-
// 滚动到指定部分
60-
const rollTo = (selector) => {
61-
heightTitle.value = selector.name;
62-
const element = document.querySelector(selector.id);
63-
const headerOffset = 45;
64-
const elementPosition = element.getBoundingClientRect().top;
65-
const offsetPosition = elementPosition + window.pageYOffset - headerOffset;
66-
67-
window.scrollTo({
68-
top: offsetPosition,
69-
behavior: "smooth"
70-
});
71-
};
57+
const onMenuClick = (item, index) => {
58+
// 可以添加额外的点击处理逻辑
59+
console.log('Menu clicked:', item.name)
60+
}
7261
7362
// 获取并设置视频课程数据
7463
const getCourses = () => {

0 commit comments

Comments
 (0)