这里监听window 的scroll实现一个页面滚动,导航菜单定位,内容联动的一个简单组件,结合一些案例,按需进行了整合,在此记录一下

效果图如下


具体实现如下


一、先创建一个NavigateTool.vue导航组件

html


<template>
<div class="searchBar navigate__bar">
<ul :class="searchBarFixed == true ? 'isFixed' :''">
<li :class="{active: navIndex===0}" @click="scrollTo(0)">区域</li>
<li :class="{active: navIndex===1}" @click="scrollTo(1)">国界</li>
<li :class="{active: navIndex===2}" @click="scrollTo(2)">宇宙</li>
<li :class="{active: navIndex===3}" @click="scrollTo(3)">银河</li>
</ul>
</div>
</template>

js

1、mounted()中 监听页面滚动

mounted() {
// 监听滚动事件
window.addEventListener('scroll', this.onScroll, false)
},
2、 destroy() 中注销监听
        destroy() {
// 必须移除监听器,不然当该vue组件被销毁了,监听器还在就会出错
window.removeEventListener('scroll', this.onScroll)
},
3、data挂载当前激活导航id

data(){
return{
navIndex:0,
searchBarFixed:false,
}
},
4、methods中添加 监听页面滚动事件方法
	/**
* 页面滚动事件监听 */
onScroll() {
// 获取所有锚点元素
const navContents = document.querySelectorAll('.home__content_comp div')
console.log(navContents.length)
// 所有锚点元素的 offsetTop
const offsetTopArr = []
navContents.forEach(item => {
offsetTopArr.push(item.offsetTop)
})
// 获取当前文档流的 scrollTop
const scrollTop = document.documentElement.scrollTop || document.body.scrollTop
// 定义当前点亮的导航下标
let navIndex = 0
for (let n = 0; n < offsetTopArr.length; n++) {
// 如果 scrollTop 大于等于第n个元素的 offsetTop 则说明 n-1 的内容已经完全不可见
// 那么此时导航索引就应该是n了
if (scrollTop >=offsetTopArr[n]) {
navIndex = n+1
}
}
navIndex = navIndex >= navContents.length? navIndex-1:navIndex;
console.log(navIndex)
this.navIndex = navIndex // 组件吸附顶部
var offsetTop = document.querySelector('.navigate__bar').offsetTop;
if (scrollTop > offsetTop) {
this.searchBarFixed = true;
} else {
this.searchBarFixed = false;
}
},
5、methods中添加导航菜单点击事件(计算页面滚动位置与组件距离顶部距离)

/**
* 跳转到指定索引的元素
* @param index
*/
scrollTo(index) {
// 获取目标的 offsetTop
// css选择器是从 1 开始计数,我们是从 0 开始,所以要 +1
// const foundEl = document.querySelector(`.home__content_comp div:nth-child(${index + 1})`);
// const elClientHeight = foundEl.clientHeight; const targetOffsetTop = document.querySelector(`.home__content_comp div:nth-child(${index+1})`).offsetTop-40
// 获取当前 offsetTop
let scrollTop = document.documentElement.scrollTop || document.body.scrollTop
// 定义一次跳 50 个像素,数字越大跳得越快,但是会有掉帧得感觉,步子迈大了会扯到蛋
const STEP = 50
// 判断是往下滑还是往上滑
if (scrollTop > targetOffsetTop) {
// 往上滑
smoothUp()
} else {
// 往下滑
smoothDown()
}
// 定义往下滑函数
function smoothDown() {
// 如果当前 scrollTop 小于 targetOffsetTop 说明视口还没滑到指定位置
if (scrollTop < targetOffsetTop) {
// 如果和目标相差距离大于等于 STEP 就跳 STEP
// 否则直接跳到目标点,目标是为了防止跳过了。
if (targetOffsetTop - scrollTop >= STEP) {
scrollTop += STEP
} else {
scrollTop = targetOffsetTop
}
document.body.scrollTop = scrollTop
document.documentElement.scrollTop = scrollTop
// 关于 requestAnimationFrame 可以自己查一下,在这种场景下,相比 setInterval 性价比更高
requestAnimationFrame(smoothDown)
}
}
// 定义往上滑函数
function smoothUp() {
if (scrollTop > targetOffsetTop) {
if (scrollTop - targetOffsetTop >= STEP) {
scrollTop -= STEP
} else {
scrollTop = targetOffsetTop
}
document.body.scrollTop = scrollTop
document.documentElement.scrollTop = scrollTop
requestAnimationFrame(smoothUp)
}
}
}

css


<style scoped lang="scss">
.searchBar {
width: 100%;
.isFixed {
position: fixed;
width: 100%;
top: 0;
left: 0;
z-index: 999;
}
ul {
height: 40px;
line-height: 40px;
display: flex;
margin:0;
padding: 0; li {
font-size: 0.8rem;
flex: 1;
display: flex;
justify-items: center;
justify-content: center;
align-items: center;
align-content: center;
position: relative;
background-color: #fff;
&.active {
color: #847ec3;
background-color: #e2e2e2;
&:after {
content: " ";
position: absolute;
height: 1px;
width: 30px;
bottom: 6px;
left:calc(50% - 15px);
border-top: 2px #847ec3 solid;
}
}
}
}
} </style>

二、再建个HomeContent.vue

这个页面就比较简单了


<template>
<div>
<naigate-tool></naigate-tool>
<!-- 内容区域 -->
<div class="home__content_comp">
<div>
This is first page.
</div>
<div>
This is second page.
</div>
<div>
This is third page.
</div>
<div>
This is fourth page.
</div> </div>
</div>
</template> <script type="text/ecmascript-6">
import NaigateTool from './NavigateTool'; export default {
name:'HomeContent',
components:{
NaigateTool
} }
</script> <style scoped>
/* 内容区的样式 */
.home__content_comp {
background-color: white;
width: 100%;
}
.home__content_comp div {
width: 100%;
height: 600px;
font-size: 26px; background-color: #7ec384;
}
.home__content_comp div:nth-child(2n) {
background-color: #847ec3;
} </style>

参考案例:

超详细Vue实现导航栏绑定内容锚点+滚动动画

vue的滚动scroll事件 实现某元素吸顶或者固定位置显示

vue横向导航条滚动到顶部固定同时瞄点对应内容(copy即用)的更多相关文章

  1. RN 使用react-navigation写可以滚动的横向导航条

    在react-native中写横向导航条,首选肯定是react-navigation的createMaterialTopTabNavigator,附上官方文档链接.https://reactnavig ...

  2. css横向导航条

    css横向导航条有两种方法 1. ul li a li{float:left} #navlist li, #navlist a{height:44px;display:block;} a{width: ...

  3. iOS:导航条滚动透明度随着tableView的滚动而变化

    来源:HelloYeah 链接:http://www.jianshu.com/p/b8b70afeda81 下面这个界面有没有觉得很眼熟.打开你手里的App仔细观察,你会发现很多都有实现这个功能.比如 ...

  4. 元素随屏幕滚动到顶部固定js效果

    网站中常见这种效果,某个广告或详情页切换tab,当屏幕向下移动时,该元素会停留在浏览器最顶部,下面ecshop模板中心教您实现js代码: 案例图: 1.首先在页面上找到该元素  加上 id =&quo ...

  5. 使用css实现移动端导航条滚动

    <div class="tab"> <div class="table-item"> <span class="tab- ...

  6. Nuxt/Vue自定义导航栏Topbar+标签栏Tabbar组件

    基于Vue.js实现自定义Topbar+Tabbar组件|仿咸鱼底部凸起导航 最近一直在倒腾Nuxt项目,由于Nuxt.js是基于Vue.js的服务端渲染框架,只要是会vue,基本能很快上手了. 一般 ...

  7. Bootstrap每天必学之导航条

    http://www.jb51.net/article/75534.htm Bootstrap每天必学之导航条,本文向大家讲解了多种多样的导航条,以及导航条中元素的实现方法,感兴趣的小伙伴们可以参考一 ...

  8. bootstrap 组件之"导航条"

    一个典型的导航条基本代码如下: <nav class="navbar navbar-default"> <div class="container&qu ...

  9. bootstrap导航条相关知识

    在导航条(navbar)中有一个背景色.而且导航条可以是纯链接(类似导航),也可以是表单,还有就是表单和导航一起结合等多种形式. 为导航条添加标题.二级菜单及状态 <div class=&quo ...

  10. Vue.js+cube-ui(Scroll组件)实现类似头条效果的横向滚动导航条

    本博主在一次个人移动端项目中,遇到这么一个需求:希望自己的项目中,头部导航条的效果可以像今日头条那样,横向滚动! 对于这样的效果,在各大移动端项目中几乎是随处可见,为什么呢? 我们都知道,对于移动端也 ...

随机推荐

  1. 【个人首测】百度文心一言 VS ChatGPT GPT-4

    昨天我写了一篇文章GPT-4牛是牛,但这几天先别急,文中我测试了用GPT-4回答ChatGPT 3.5 和 Notion AI的问题,大家期待的图片输入也没有出现. 昨天下午百度发布了文心一言,对标C ...

  2. CF1037H Security题解

    根据字典序的定义,位置大的大于长度长的,长度长的大于长度短的. 所以我们贪心,先追求长度长的,再追求后面的位置大的,再追求前面的位置大的. 我们要一个能遍历子串的结构,就选 SAM 得了. 还有个限制 ...

  3. Shell脚本监控Centos 7系统运行状态

    #!/usr/bin/bash ## @date: 2021-08-17 ## This is a script for security operation indicator monitoring ...

  4. Vue 相关整理

    一 谈谈对 keep-alive 的了解? keep-alive 是Vue内置的一个组件,可以使被包含的组件保留状态,避免重新渲染,其有以下特性: * 一般结合路由和动态组件一起使用,用于缓存组件: ...

  5. 万字血书React—走近React

    配置开发环境 脚手架工具create-react-app 储备知识:终端或命令行.代码编辑器 React官方中文文档 create-react-app 其是基于Node的快速搭建React项目的脚手架 ...

  6. TypeScript 学习笔记 — 基于对象操作的内置类型的使用(十二)

    目录 1.Partial 转化可选属性 (?) 2.Required 转化必填属性 (-?) 3.Readonly 转化仅读属性 (readonly) Mutate(非内置,与 Readonly 相对 ...

  7. 什么时候需要使用try-catch

    代码执行预料不到的情况,或出错的可能性很大时,使用try-catch语句 构造一个文件输入流(上传文件时,线上环境的内存情况不确定)出错的可能性很大 文件上传写入, 数据库事务的提交,还有摄像头和打印 ...

  8. 【SpringMVC】(三)

    HTTPMessageConverter HttpMessageConverter报文信息转换器,将请求报文转换为java对象,或将java对象转换为响应报文. 1 @ResquestBody Res ...

  9. LeetCode 周赛 341 场,模拟 / 树上差分 / Tarjan 离线 LCA / DFS

    本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 提问. 大家好,我是小彭. 上周末有单双周赛,双周赛我们讲过了,单周赛那天早上有事没参加,后面做了虚拟竞赛,然后整个 ...

  10. 2021.05.09【NOIP提高组】模拟赛总结

    2021.05.09[NOIP提高组]模拟赛总结 T1 T2