vue切换菜单,vue菜单选中。跳转页面通过原生js设置选中样式。vue中使用原生js方法。js 找到当前对象的兄弟对象。js获取子节点。js获取父节点。js获取当前元素的同级节点 电脑版发表于:2019/9/16 21:31 ### vue切换菜单,跳转页面通过原生js设置选中样式 可以利用上面那个js获取当前元素的同级节点后先设置默认的样式,然后在设置点击这个元素的一个选中样式即可。 #### vue页面元素: ``` <div class="menuwapper" > <div class="menuitem">学期报告</div> <div class="menuitem menuitemfocus" @click="jump('/user/myfeedback',$event)">我的反馈</div> <div class="menuitem">我的评估</div> <div class="menuitem" @click="jump('/user/mylabroom',$event)">我的实验</div> <div class="menuitem">我的产教</div> <div class="menuitem">我的考试</div> <div class="menuitem">个人信息</div> </div> ``` #### 切换的方法: ``` methods: { jump(path, event) { //先把元素的样式全部回归成默认状态 let childNodes = event.currentTarget.parentNode.childNodes for (let index = 0; index < childNodes.length; index++) { const element = childNodes[index]; element.className = "menuitem" } //给当前点击的元素添加选中样式 event.currentTarget.className = "menuitem menuitemfocus" //进行页面跳转 this.$router.push(path) } } ``` 这样虽然点击的时候可以切换成功,但是在页面刚开始加载的时候是有问题的,所以需要单独处理一下刚开始加载的时候菜单选中的问题。也可以封装一个菜单选中的方法,在页面加载的时候以及页面切换的时候调用。 #### 封装一个菜单选中的方法,在页面加载的时候以及页面切换的时候调用 ``` watch: { // 监听路由变化的时候在进行菜单选中 $route(to, from) { console.log('导航页to', to) this.choiseMenu(to.fullPath) } }, mounted() { const routePath = this.$route.path this.choiseMenu(routePath) }, methods: { // 菜单选中,可以跳转的路由在判断应该选中的菜单 choiseMenu(routePath) { const childNodes = document.getElementById('usersubmenu').getElementsByTagName('div') for (let index = 0; index < childNodes.length; index++) { const element = childNodes[index] console.log(element.getAttribute('href')) if (routePath === element.getAttribute('href')) { element.className = 'menuitem menuitemfocus' console.log('相同进来设置了') // alert('相同进来设置了' + element.getAttribute('href')) } else { element.className = 'menuitem' } } }, jump(event) { const href = event.currentTarget.getAttribute('href') this.$router.push(href) } } ``` 注意在页面切换的时候调用不是点击菜单方法跳转方法里边,如果在这个方法里边直接通过this.$route.path或者是localhost.href去获取地址,是当前这个页面的地址,而不是你想要跳转的页面地址,所以可以监听路由的方法,在这个监听方法里边去调用就行了。当然在跳转的时候调用也是可以的,只是不要去通过this.$route.path类似的方法获取当前的,而是要获取你要跳转到的目标地址,如下写法不用监听也是可以的 ``` jump(event) { const href = event.currentTarget.getAttribute('href') // 菜单选中 this.choiseMenu(href) this.$router.push(href) } ``` **还有使用这种样式绑定的方式可能还要简单一些**:https://www.tnblog.net/xiuxin/article/details/7959 也可以这种,绑定样式可以使用方法的形式处理,这样写逻辑更方便了,比如`:class="dealChoise(item.schoolID)"` ``` <div class="shcoolItem" :class="dealChoise(item.schoolID)" @click="changeSchool(item.schoolID)" v-for="(item, index) in schoolList" v-bind:key="index"> {{ item.schoolName }}</div> ``` 处理的方法如下,达成某种条件就返回一个选中样式即可 ``` methods: { dealChoise: function (schoolID) { // 找到相同的id就给一个cur样式,达到选中的效果 if (schoolID === this.$getSchoolId()) { return "cur" } } } ``` 就上面那么一点代码就可以实现这种校区切换页面刷新之后的选中效果了 ![](https://img.tnblog.net/arcimg/aojiancc2/3d20cb1d383242a980f0f1ca4bc59ec4.png) #### 把整体页面贴一下吧 ``` <template> <div class="app-container"> <div class="usercenter_left"> <div class="userinfo"> <div class="headimgwapper"> <img class="headimg" src="https://img.tnblog.net/userdata/heads/dbc68332d521436c983fbc3adc6d9c7f.jpeg" alt="" srcset=""> </div> <div style="padding:20px"> <div class="sumtimes"> <span style="background: #FE4444;height: 20px;width: 20px;color:#fff;display: inline-block;border-radius: 50px;line-height: 20px;text-align: center;">累</span> <span>计时长:506小时46分2</span> </div> <div class="onlinetimes"> <span style="background: #EA740B;height: 20px;width: 20px;color:#fff;display: inline-block;border-radius: 50px;line-height: 20px;text-align: center;">今</span> <span>日时长:25小时46分50秒</span> </div> </div> </div> <div id="usersubmenu" class="menuwapper"> <div class="menuitem" href="/user/index/term-report" @click="jump($event)">学期报告</div> <div class="menuitem" href="/user/index/myfeedback" @click="jump($event)">我的反馈</div> <div class="menuitem">我的评估</div> <div class="menuitem" href="/user/index/mylabroom" @click="jump($event)">我的实验</div> <div class="menuitem">我的产教</div> <div class="menuitem">我的考试</div> <div class="menuitem">个人信息</div> </div> </div> <div class="usercenter_right"> <router-view /> </div> </div> </template> <script> export default { data() { return { courseID: '', labId: '', chapter: {} } }, watch: { // 监听路由变化的时候在进行菜单选中 // $route(to, from) { // console.log('导航页to', to) // this.choiseMenu(to.fullPath) // } }, mounted() { const routePath = this.$route.path this.choiseMenu(routePath) }, methods: { // 菜单选中,可以跳转的路由在判断应该选中的菜单 choiseMenu(routePath) { const childNodes = document.getElementById('usersubmenu').getElementsByTagName('div') for (let index = 0; index < childNodes.length; index++) { const element = childNodes[index] console.log(element.getAttribute('href')) if (routePath === element.getAttribute('href')) { element.className = 'menuitem menuitemfocus' console.log('相同进来设置了') // alert('相同进来设置了' + element.getAttribute('href')) } else { element.className = 'menuitem' } } }, jump(event) { const href = event.currentTarget.getAttribute('href') // 菜单选中 this.choiseMenu(href) this.$router.push(href) } } } </script> <style scoped="scoped"> .app-container { width: 1200px; /* min-height: 200px; */ display: flex; margin: 20px auto; } .usercenter_left { width: 235px; } .usercenter_left .userinfo { background-color: #fff; padding-top: 20px; padding-bottom: 10px; } .usercenter_left .headimgwapper { text-align: center; } .usercenter_left .headimg { width: 100px; height: 100px; border-radius: 50%; } .usercenter_left .menuwapper { min-height: 300px; margin-top: 20px; /* width: 240px; */ background-color: #fff; } .usercenter_left .sumtimes { font-size: 13px; font-family: MicrosoftYaHei-, MicrosoftYaHei; font-weight: normal; color: #000000; } .usercenter_left .onlinetimes { font-size: 13px; margin-top: 10px; font-family: MicrosoftYaHei-, MicrosoftYaHei; font-weight: normal; color: #000000; } .menuwapper .menuitem { text-align: center; /* width: 66px; */ height: 60px; font-size: 15px; font-family: MicrosoftYaHei-, MicrosoftYaHei; font-weight: normal; color: #747774; cursor: pointer; letter-spacing: 2px; /* line-height: 21px; */ } .menuwapper .menuitem:first-child { padding-top: 34px; } .menuwapper .menuitem:hover { color: #1C6CB8; } .menuwapper .menuitemfocus { color: #1C6CB8; } .usercenter_right { flex: 1; background-color: #fff; margin-left: 20px; /* min-height: 200px; */ } </style> ``` #### 把这块使用到的路由配置也贴一下吧 其实这块也差不多是一个二级的布局页,下面子级,上面还有父级 ``` // 图谱 const userCenter = [ /** * 课程资源 */ { path: '/user', name: 'UserNav', component: () => import('@/pages/user-center/components/layout.vue'), redirect: '/user/major', // 设置默认打开的页面 children: [ { path: '/user/atlas-major', name: 'AtlasMajor', component: () => import('@/pages/user-center/atlas-major.vue'), meta: { title: '专业图谱' } }, { path: '/user/atlas-growth', name: 'AtlasGrowh', component: () => import('@/pages/user-center/atlas-growth.vue'), meta: { title: '成长图谱' } }, { path: '/user/index', name: 'UserIndex', component: () => import('@/pages/user-center/index.vue'), redirect: '/user/index/myfeedback', // 设置默认打开的页面 meta: { title: '个人中心' }, children: [ { path: '/user/index/term-report', name: 'UserIndexTermReport', component: () => import('@/pages/user-center/submenu/term-report.vue'), meta: { title: '学期报告' } }, { path: '/user/index/myfeedback', name: 'MyFeedback', component: () => import('@/pages/user-center/submenu/myfeedback.vue'), meta: { title: '我的反馈' } }, { path: '/user/index/mylabroom', name: 'MyFeedback', component: () => import('@/pages/user-center/submenu/mylabroom.vue'), meta: { title: '我的实验' } } ] } ] } ] export default userCenter ``` --- --- #### 还可以参考一下这样的写法 ``` <template> <div class="common-nav"> <div class="nav is-flex"> <div class="nav-left"> <router-link to="/" class="nav-left-a" :class="{on: isCurrent('/')}">首页 </router-link> <router-link to="/article" class="nav-left-a" :class="{on: isCurrent('/article')}">文章 </router-link> <router-link to="/about" class="nav-left-a" :class="{on: isCurrent('/about')}">关于 </router-link> </div> </div> </div> </template> <script> export default { name: "common-nav", data() { return {} }, methods: { isCurrent(path) { console.log(this.$route.path) return this.$route.path === path } } } </script> ``` --- --- ### js获取子节点。js获取父节点等 ``` var chils= s.childNodes; //得到s的全部子节点。不过它会把换行和空格也当成节点信息,不推荐使用。 var c = document.getElementById("price").children;//通过children来获取子节点,推荐使用 const childNodes = document.getElementById('usersubmenu').getElementsByTagName('div')//根据元素获取子元素推荐使用 var par=s.parentNode; //得到s的父节点 var ns=s.nextSibling; //获得s的下一个兄弟节点 var ps=s.previousSibling; //得到s的上一个兄弟节点 var fc=s.firstChild; //获得s的第一个子节点 var lc=s.lastChild; //获得s的最后一个子节点 ``` 参考:https://www.tnblog.net/notebook/article/details/7920 ### js获取当前元素的同级节点 先获取父级,在获取子级就可以了撒 ``` let childNodes = event.currentTarget.parentNode.childNodes ``` ### 原生的JS获取ID为test的元素下的子元素。 ``` let a = docuemnt.getElementById("test").getElementsByTagName("div"); ``` 方法2:不推荐 ``` let b =document.getElementById("test").childNodes; ``` 方法3:推荐 ``` let b =document.getElementById("test").children; ```