工作需要做一个带滑块效果的导航栏,初步想法是用element的导航组件去做,后面摸坑结合各位大佬的博客初步实现效果,话不多说,直接上代码,记录一下爬坑之旅
1 <template>
2 <div class="y-nav">
3 <el-row class="nav">
4 <el-menu
5 :default-active="$route.path"
6 class="el-menu-demo"
7 mode="horizontal"
8 @select="handleSelect"
9 text-color="#fff"
10 >
11 <el-menu-item index="/index">
12 <router-link
13 to="/"
14 @mouseover.native="itransition($event )"
15 @mouseout.native="outtransition($event)"
16 >首页</router-link>
17 </el-menu-item>
18 <el-menu-item index="/leaderboard/leaderlist">
19 <router-link
20 :to="{name:'leaderboard'}"
21 @mouseover.native="itransition($event )"
22 @mouseout.native="outtransition($event)"
23 >排行榜</router-link>
24 </el-menu-item>
25 <el-menu-item index="/library">
26 <router-link
27 :to="{name:'library'}"
28 @mouseover.native="itransition($event )"
29 @mouseout.native="outtransition($event)"
30 >书库</router-link>
31 </el-menu-item>
32 <el-menu-item index="/recharge">
33 <router-link
34 to="/recharge"
35 @mouseover.native="itransition($event )"
36 @mouseout.native="outtransition($event)"
37 >充值</router-link>
38 </el-menu-item>
39 <el-menu-item index="/vip">
40 <router-link
41 :to="{name:'vip'}"
42 @mouseover.native="itransition($event )"
43 @mouseout.native="outtransition($event)"
44 >VIP专区</router-link>
45 </el-menu-item>
46 <el-menu-item index="/institution">
47 <router-link
48 to="/institution"
49 @mouseover.native="itransition($event )"
50 @mouseout.native="outtransition($event)"
51 >院校</router-link>
52 </el-menu-item>
53 <el-menu-item index="/community">
54 <router-link
55 to="/community"
56 @mouseover.native="itransition($event )"
57 @mouseout.native="outtransition($event)"
58 >社区</router-link>
59 </el-menu-item>
60 <el-menu-item index="/author">
61 <router-link
62 to="/author"
63 @mouseover.native="itransition($event )"
64 @mouseout.native="outtransition($event)"
65 >作者福利</router-link>
66 </el-menu-item>
67
68 <div class="moveblock" ref="moveblock"></div>
69 </el-menu>
70 </el-row>
71 </div>
72 </template>
73 <script>
74 export default {
75 data() {
76 return {};
77 },
78 // created() {
79 // console.log(document.querySelector(".el-menu>.is-active").offsetLeft);
80 // },
81 mounted() {
82 //获取menu宽度
83 let menuwidth = document.querySelector(".el-menu-item.is-active>a")
84 .offsetWidth;
85 //获取li
86 let liwidth = document.querySelectorAll(".el-menu li");
87 //背景
88 let moveblock = document.querySelector(".moveblock");
89 //设置背景的宽度
90 // moveblock.style.width = liwidth[0].offsetWidth + "px";
91 let selfLeft = document.querySelector(".el-menu .is-active").offsetLeft;
92
93 moveblock.style.width = menuwidth + "px";
94
95 let winwidth = document.body.clientWidth;
96 // console.log("base:" + selfLeft);
97 moveblock.style.left = selfLeft + 35 + "px";
98 },
99 methods: {
100 handleSelect(key, keyPath) {
101 console.log(key, keyPath);
102 },
103 itransition($event) {
104 //为悬浮元素添加hover
105 // $event.currentTarget.className = "router-link-active hover";
106 //获取元素的left值
107 let left = $event.currentTarget.getBoundingClientRect().left;
108 //获取移动元素
109 let moveblock = document.querySelector(".moveblock");
110 //获取可视区域的宽度
111 let winwidth = document.body.clientWidth;
112 if (winwidth > 1200) {
113 moveblock.style.left = left - (winwidth - 1200) / 2 + "px";
114 } else {
115 moveblock.style.left = left + "px";
116 }
117 },
118 outtransition($event) {
119 // $event.currentTarget.className = "router-link-active";
120 //获取移动元素
121 let moveblock = document.querySelector(".moveblock");
122 //获取is-active的offsetLeft
123 let selfLeft = document.querySelector(".el-menu .is-active").offsetLeft;
124 // let selfLeft = this.$refs.moveblock.offsetLeft;
125 moveblock.style.left = selfLeft + 35 + "px";
126 }
127 }
128 };
129 </script>
130 <style lang="sass">
131 @import "@/assets/css/public/header/nav.scss";
132 </style>
一、element组件的is-active
:default-active="$route.path"
导航的is-active,当时纠结了好久,百度了好久看到这个办法,还是不行,后来才注意到要结合
<el-menu-item
index="/index">
获取当前的路由路径和index中的数据进行对比,添加is-active
二、关于刷新后的元素offsetleft问题
最初的想法是
let selfLeft = document.querySelectorAll(".el-menu .is-active").offsetLeft;
刷新后发现selfLeft的值为undefined,怀疑是mounted中无法获取刷新后元素的dom,先后试验了$nextTick 和setTimeout均无法解决问题,后将整体代码放到created()中仍未解决问题,
在created()中直接打印document.querySelectorAll(".el-menu .is-active").offsetLeft;也是现实undefined,document.querySelectorAll(".el-menu .is-active")为一个数组结构,果断换用
let selfLeft = document.querySelector(".el-menu .is-active").offsetLeft;
出现数据,至此组件效果基本实现,代码结构稍显混乱,感觉有很大的优化空间,望各位大佬提出建议~
刚测试的时候发现bug,在子路由下无法匹配is-active,现进行更改
1 // 将default-active绑定到dfactive上
2 <el-menu
3 :default-active="dfactive"
4 class="el-menu-demo"
5 mode="horizontal"
6 @select="handleSelect"
7 text-color="#fff"
8 >
9 // 截取当前路由第一层路径的地址
10 data() {
11 return {
12 dfactive:this.$route.path.split("/")[1]
13 };
14 }
这样就能匹配子路由的链接了~~~
来源:oschina
链接:https://my.oschina.net/u/4323253/blog/3527632