一、效果图

vue+element ui实现页面平滑滚动,滚动监听(导航栏根据内容块滑动改变状态)_导航栏

二、点击导航栏页面平滑滚动

1.首先在子组件设置锚点

如图中给与导航栏对应的四个div设置锚点id

vue+element ui实现页面平滑滚动,滚动监听(导航栏根据内容块滑动改变状态)_锚点_02


2.在子组件编写滚动方法

监听路由的变化

vue+element ui实现页面平滑滚动,滚动监听(导航栏根据内容块滑动改变状态)_ico_03


实现fetchData函数

可以看到,该方法获取了路由中通过query传递的参数aId,该参数是从父组件中所写的导航栏元素中传过来的,后面会看到。aId参数与锚点id一一对应,获取到该值后便使用scrollIntoView方法控制滚动。

vue+element ui实现页面平滑滚动,滚动监听(导航栏根据内容块滑动改变状态)_ico_04


3.在父组件中实现点击导航栏对象传递query参数

<el-submenu index="/fileSystemDeletion?aId=fileSystemDeletion">              
<template slot="title"><i class="el-icon-document"></i>文件系统数据库保护</template>
<el-menu-item-group>
<router-link :to="{ name: 'fileSystemDeletion', query: { aId:'fileSystemDeletion' }}"> <el-menu-item index="/fileSystemDeletion" ><i class="el-icon-key"></i>增删改服务器</el-menu-item></router-link>
<router-link :to="{ name: 'fileSystemDeletion', query: { aId:'fileSystemBackup' }}"><el-menu-item index="/fileSystemBackup" ><i class="el-icon-key"></i>备份</el-menu-item></router-link>
<router-link :to="{ name: 'fileSystemDeletion', query: { aId:'fileSystemRecover' }}"><el-menu-item index="/fileSystemRecover"><i class="el-icon-key"></i>恢复</el-menu-item></router-link>
<router-link :to="{ name: 'fileSystemDeletion', query: { aId:'fileSystemTermination' }}"><el-menu-item index="/fileSystemTermination"><i class="el-icon-key"></i>终止计划</el-menu-item></router-link>
</el-menu-item-group>
</el-submenu>

是对element ui的菜单组件进行了修改,点击导航栏中下选项就会通过路由query传递aId值

4 存在的问题解决
1)以上虽然在单个子组件页面内可以实现很好的平滑滚动,但是当切换到另外一个子组件页面时,页面停留在与上一个子组件页面相同的位置。
为解决这个问题,我们在父组件添加方法,当路由中的name有所改变时(即更换到了另一个子组件页面),我们便使屏幕滚动到顶部。

2)还有一个问题就是设置导航栏中默认激活项

解决方法:

我们在el-menu中设置:default-active和@open如下

vue+element ui实现页面平滑滚动,滚动监听(导航栏根据内容块滑动改变状态)_vue相关_05


js部分实现监听路由变化,改变导航栏选中状态

vue+element ui实现页面平滑滚动,滚动监听(导航栏根据内容块滑动改变状态)_锚点_06


在methods中实现相应的方法

vue+element ui实现页面平滑滚动,滚动监听(导航栏根据内容块滑动改变状态)_导航栏_07

可以看到在fetchData中,用index存放当前路由的name,然后select赋值为存放在本地内存中的id(原来路由的name值),若原来的name不是空值,则判断二者是否相等,若不相等则证明从一个子组件页面跳转到了另一个子组件页面,所以我们将页面刷新定位到顶部。并将新的路由中的name,替换原name存放与缓存中的id中。——解决问题1

每当监听到路由发生改变,将新的route.query.id赋值给defaultAc,以改变激活项。 同时toOpen方法,使得点击导航的title部分时便更换route——解决问题2

三、滚动监听

1.在父组件中监听滚动条,并将当前位置传递给子组件,子组件将判断后的结果值,通过调用父组件方法改变导航栏激活选项

由于滚动条是属于父组件的,所以在父组件中监听,下方是父组件中引入子组件的入口

vue+element ui实现页面平滑滚动,滚动监听(导航栏根据内容块滑动改变状态)_导航栏_08

实现getScroll方法

vue+element ui实现页面平滑滚动,滚动监听(导航栏根据内容块滑动改变状态)_导航栏_09


<1>父组件调用子组件方法

在调用子组件的入口处添加 ref,如本例中,加上了ref=‘child’,然后需要调用的地方,用this.$refs.child.methods (其中methods是子组件的方法名)<2>子组件调用父组件方法

本例中,先在调用子组件的入口绑定方法@func=“isActived”,其中isActived是父组件的方法

vue+element ui实现页面平滑滚动,滚动监听(导航栏根据内容块滑动改变状态)_ico_10

本例中,该方法如上,是为了实现,子组件页面滚动到相应位置后,对父组件的导航栏激活项进行改变

2.子组件页面对父组件传过来的页面scrollTop与锚点位置比对,以判断应当激活的导航栏选项

  • 其中onScroll方法通过参数currentScrollTop接受到父组件传过来的当前元素的位置。
  • 为每一个锚点块增加相同的class="anchor’"属性,然后通过document.querySelectAll(’.anchor’),获取到所有锚点块元素对象,并将他们的scrollTop存放在数组中,然后通过循环对比当前位置与相关锚点位置的关系,从而调用父组件的方法改变menu组件的default-active属性值,从而改变激活状态。
  • 由于最后一个锚点内容可能比较短,因而无法滚动到标题处,所以通过父组件中监听滚动条是否到达了底部,若到达了底部则调用子组件的toBottom方法

vue+element ui实现页面平滑滚动,滚动监听(导航栏根据内容块滑动改变状态)_锚点_11