Bootstrap滚动监听组件scrollspy.js使用方法详解
发布时间 - 2026-01-11 02:26:12 点击率:次其实滚动监听使用的情况还是很多的,比如导航居于右侧,当主题内容滚动某一块的时候,右侧导航对应的要高亮。

实现功能
1、当滚动区域内设置的hashkey距离顶点到有效位置时,就关联设置其导航上的指定项
2、导航必须是 .nav > li > a 结构,并且a上href或data-target要绑定hashkey
3、菜单上必须有.nav样式
4、滚动区域的data-target与导航父级Id(一定是父级)要一致。
<div id="selector" class="navbar navbar-default"> <ul class="nav navbar-nav"> <li><a href="#one">one</a> </li> <li><a href="#two">two</a> </li> <li><a href="#three">three</a> </li> </ul> </div> <div data-spy="scroll" data-target="#selector" style="height:100px; overflow:hidden;overflow-y: auto;" > <h4 id="one" >ibe</h4><p>One的具体内容<br/>One的具体内容<br/>One的具体内容<br/>One的具体内容<br/>One的具体内容<br/>One的具体内容<br/></p> <h4 id="two" >two</h4><p>One的具体内容<br/>One的具体内容<br/>One的具体内容<br/>One的具体内容<br/>One的具体内容<br/>One的具体内容<br/></p> <h4 id="three" >three</h4><p>One的具体内容<br/>One的具体内容<br/>One的具体内容<br/>One的具体内容<br/>One的具体内容<br/>One的具体内容<br/></p> </div>
下面来看一下实现的具体代码,原理:当滚动容器内的hashkey位置距离容器顶部只有 offset设置的值,就会设置导航中对应的href高亮。
ScrollSpy构造函数
首先新建一个构造函数,如下:
function ScrollSpy(element, options) {
this.$body = $(document.body)
this.$scrollElement = $(element).is(document.body) ? $(window) : $(element)
this.options = $.extend({}, ScrollSpy.DEFAULTS, options)
this.selector = (this.options.target || '') + ' .nav li > a'
this.offsets = []
this.targets = []
this.activeTarget = null
this.scrollHeight = 0
this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this))
this.refresh()
this.process()
}
该构造函数主要干了啥:
1.基本设置,主要是设置当前滚动元素是设置的body还是具体的某一块元素;其次是导航的结构要是.nav li > a的结构,也就是你的菜单中也要有.nav这个class。
2.监听元素滚动的时候,执行process方法。
3.同时初始化的时候也执行了refresh与process方法。
下面讲解一下这几个方法。
getScrolHeight方法
获取滚动容器的内容高度(包含被隐藏部分)
this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
refresh方法
刷新并存储滚动容器内各hashkey的值
ScrollSpy.prototype.refresh = function () {
var that = this
var offsetMethod = 'offset'
var offsetBase = 0
this.offsets = []
this.targets = []
this.scrollHeight = this.getScrollHeight()
if (!$.isWindow(this.$scrollElement[0])) {
offsetMethod = 'position'
offsetBase = this.$scrollElement.scrollTop()
}
this.$body
.find(this.selector)
.map(function () {
var $el = $(this)
var href = $el.data('target') || $el.attr('href')
var $href = /^#./.test(href) && $(href)
return ($href
&& $href.length
&& $href.is(':visible')
&& [[$href[offsetMethod]().top + offsetBase, href]]) || null
})
.sort(function (a, b) { return a[0] - b[0] })
.each(function () {
that.offsets.push(this[0])
that.targets.push(this[1])
})
}
它主要实现了什么呢?
1.默认用offset来获取定位值,如果滚动区域不是window则用position来获取
if (!$.isWindow(this.$scrollElement[0])) {
offsetMethod = 'position'
offsetBase = this.$scrollElement.scrollTop()
}
2.根据导航上的hashkey来遍历获取 滚动区域内的hashkey对应的offset值:
this.$body
.find(this.selector)
.map(function () {
var $el = $(this)
var href = $el.data('target') || $el.attr('href')
var $href = /^#./.test(href) && $(href)
return ($href
&& $href.length
&& $href.is(':visible')
&& [[$href[offsetMethod]().top + offsetBase, href]]) || null
})
.sort(function (a, b) { return a[0] - b[0] })
.each(function () {
that.offsets.push(this[0])
that.targets.push(this[1])
})
process方法
滚动条事件触发函数,用于计算当前需要高亮那个导航菜单
ScrollSpy.prototype.process = function () {
var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
var scrollHeight = this.getScrollHeight()
var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height()
var offsets = this.offsets
var targets = this.targets
var activeTarget = this.activeTarget
var i
if (this.scrollHeight != scrollHeight) {
this.refresh()
}
if (scrollTop >= maxScroll) {
return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
}
if (activeTarget && scrollTop < offsets[0]) {
this.activeTarget = null
return this.clear()
}
for (i = offsets.length; i--;) {
activeTarget != targets[i]
&& scrollTop >= offsets[i]
&& (offsets[i + 1] === undefined || scrollTop < offsets[i + 1])
&& this.activate(targets[i])
}
}
主要作用:
1.获取滚动容器已滚动距离:
var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
2.滚动容器可以滚动的最大高度:
var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height()
3.设置滚动元素逻辑,给当前匹配元素添加高亮:
for (i = offsets.length; i--;) {
activeTarget != targets[i]
&& scrollTop >= offsets[i]
&& (offsets[i + 1] === undefined || scrollTop < offsets[i + 1])
&& this.activate(targets[i])
}
active方法
设置指定的导航菜单高亮
ScrollSpy.prototype.activate = function (target) {
this.activeTarget = target
this.clear()
var selector = this.selector +
'[data-target="' + target + '"],' +
this.selector + '[href="' + target + '" rel="external nofollow" rel="external nofollow" ]'
var active = $(selector)
.parents('li')
.addClass('active')
if (active.parent('.dropdown-menu').length) {
active = active
.closest('li.dropdown')
.addClass('active')
}
active.trigger('activate.bs.scrollspy')
}
clear方法
清除所有高亮菜单
ScrollSpy.prototype.clear = function () {
$(this.selector)
.parentsUntil(this.options.target, '.active')
.removeClass('active')
}
源码
+function ($) {
'use strict';
// SCROLLSPY CLASS DEFINITION
// ==========================
function ScrollSpy(element, options) {
this.$body = $(document.body)
this.$scrollElement = $(element).is(document.body) ? $(window) : $(element)
this.options = $.extend({}, ScrollSpy.DEFAULTS, options)
this.selector = (this.options.target || '') + ' .nav li > a'
this.offsets = []
this.targets = []
this.activeTarget = null
this.scrollHeight = 0
this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this))
this.refresh()
this.process()
}
ScrollSpy.VERSION = '3.3.7'
ScrollSpy.DEFAULTS = {
offset: 10
}
ScrollSpy.prototype.getScrollHeight = function () {
return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
}
ScrollSpy.prototype.refresh = function () {
var that = this
var offsetMethod = 'offset'
var offsetBase = 0
this.offsets = []
this.targets = []
this.scrollHeight = this.getScrollHeight()
if (!$.isWindow(this.$scrollElement[0])) {
offsetMethod = 'position'
offsetBase = this.$scrollElement.scrollTop()
}
this.$body
.find(this.selector)
.map(function () {
var $el = $(this)
var href = $el.data('target') || $el.attr('href')
var $href = /^#./.test(href) && $(href)
return ($href
&& $href.length
&& $href.is(':visible')
&& [[$href[offsetMethod]().top + offsetBase, href]]) || null
})
.sort(function (a, b) { return a[0] - b[0] })
.each(function () {
that.offsets.push(this[0])
that.targets.push(this[1])
})
}
ScrollSpy.prototype.process = function () {
var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
var scrollHeight = this.getScrollHeight()
var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height()
var offsets = this.offsets
var targets = this.targets
var activeTarget = this.activeTarget
var i
if (this.scrollHeight != scrollHeight) {
this.refresh()
}
if (scrollTop >= maxScroll) {
return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
}
if (activeTarget && scrollTop < offsets[0]) {
this.activeTarget = null
return this.clear()
}
for (i = offsets.length; i--;) {
activeTarget != targets[i]
&& scrollTop >= offsets[i]
&& (offsets[i + 1] === undefined || scrollTop < offsets[i + 1])
&& this.activate(targets[i])
}
}
ScrollSpy.prototype.activate = function (target) {
this.activeTarget = target
this.clear()
var selector = this.selector +
'[data-target="' + target + '"],' +
this.selector + '[href="' + target + '" rel="external nofollow" rel="external nofollow" ]'
var active = $(selector)
.parents('li')
.addClass('active')
if (active.parent('.dropdown-menu').length) {
active = active
.closest('li.dropdown')
.addClass('active')
}
active.trigger('activate.bs.scrollspy')
}
ScrollSpy.prototype.clear = function () {
$(this.selector)
.parentsUntil(this.options.target, '.active')
.removeClass('active')
}
// SCROLLSPY PLUGIN DEFINITION
// ===========================
function Plugin(option) {
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.scrollspy')
var options = typeof option == 'object' && option
if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))
if (typeof option == 'string') data[option]()
})
}
var old = $.fn.scrollspy
$.fn.scrollspy = Plugin
$.fn.scrollspy.Constructor = ScrollSpy
// SCROLLSPY NO CONFLICT
// =====================
$.fn.scrollspy.noConflict = function () {
$.fn.scrollspy = old
return this
}
// SCROLLSPY DATA-API
// ==================
$(window).on('load.bs.scrollspy.data-api', function () {
$('[data-spy="scroll"]').each(function () {
var $spy = $(this)
Plugin.call($spy, $spy.data())
})
})
}(jQuery);
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
# Bootstrap
# 滚动监听
# scrollspy.js
# bootstrap监听滚动实现头部跟随滚动
# BootStrap下拉菜单和滚动监听插件实现代码
# 学习Bootstrap滚动监听 附调用方法
# 全面解析Bootstrap中scrollspy(滚动监听)的使用方法
# Bootstrap教程JS插件滚动监听学习笔记分享
# Bootstrap滚动监听(Scrollspy)插件详解
# Bootstrap每天必学之滚动监听
# Bootstrap+Vue滑动监听Scrollspy实现餐厅餐品展示
# 具体内容
# 容器内
# 就会
# 要有
# 遍历
# 什么呢
# 中也
# 干了
# 这几个
# 绑定
# 点到
# 大家多多
# 新建一个
# 则用
# 主要是
# 滚动条
# 实现了
# API
# offset
# load
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
laravel怎么配置Redis作为缓存驱动_laravel Redis缓存配置教程
Laravel中间件如何使用_Laravel自定义中间件实现权限控制
UC浏览器如何切换小说阅读源_UC浏览器阅读源切换【方法】
b2c电商网站制作流程,b2c水平综合的电商平台?
Laravel如何处理跨站请求伪造(CSRF)保护_Laravel表单安全机制与令牌校验
HTML 中如何正确使用模板变量为元素的 name 属性赋值
php在windows下怎么调试_phpwindows环境调试操作说明【操作】
高端企业智能建站程序:SEO优化与响应式模板定制开发
php485函数参数是什么意思_php485各参数详细说明【介绍】
网站建设整体流程解析,建站其实很容易!
Laravel如何配置.env文件管理环境变量_Laravel环境变量使用与安全管理
Laravel用户认证怎么做_Laravel Breeze脚手架快速实现登录注册功能
公司门户网站制作流程,华为官网怎么做?
今日头条AI怎样推荐抢票工具_今日头条AI抢票工具推荐算法与筛选【技巧】
Laravel怎么导出Excel文件_Laravel Excel插件使用教程
深入理解Android中的xmlns:tools属性
Laravel中的Facade(门面)到底是什么原理
儿童网站界面设计图片,中国少年儿童教育网站-怎么去注册?
矢量图网站制作软件,用千图网的一张矢量图做公司app首页,该网站并未说明版权等问题,这样做算不算侵权?应该如何解决?
魔方云NAT建站如何实现端口转发?
Laravel如何操作JSON类型的数据库字段?(Eloquent示例)
Laravel distinct去重查询_Laravel Eloquent去重方法
Laravel如何使用Spatie Media Library_Laravel图片上传管理与缩略图生成【步骤】
如何在万网ECS上快速搭建专属网站?
详解免费开源的.NET多类型文件解压缩组件SharpZipLib(.NET组件介绍之七)
Laravel怎么在Blade中安全地输出原始HTML内容
Laravel的契約(Contracts)是什么_深入理解Laravel Contracts与依赖倒置
阿里云高弹*务器配置方案|支持分布式架构与多节点部署
Laravel怎么实现模型属性转换Casting_Laravel自动将JSON字段转为数组【技巧】
laravel怎么使用数据库工厂(Factory)生成带有关联模型的数据_laravel Factory生成关联数据方法
如何安全更换建站之星模板并保留数据?
如何用y主机助手快速搭建网站?
如何在阿里云ECS服务器部署织梦CMS网站?
Android okhttputils现在进度显示实例代码
Laravel怎么使用Blade模板引擎_Laravel模板继承与Component组件复用【手册】
微信公众帐号开发教程之图文消息全攻略
如何在Tomcat中配置并部署网站项目?
Laravel的Blade指令怎么自定义_创建你自己的Laravel Blade Directives
用v-html解决Vue.js渲染中html标签不被解析的问题
Laravel怎么在Controller之外的地方验证数据
Swift开发中switch语句值绑定模式
如何登录建站主机?访问步骤全解析
如何在云主机上快速搭建网站?
Laravel怎么进行浏览器测试_Laravel Dusk自动化浏览器测试入门
如何在局域网内绑定自建网站域名?
千问怎样用提示词获取健康建议_千问健康类提示词注意事项【指南】
如何快速重置建站主机并恢复默认配置?
如何选择可靠的免备案建站服务器?
Laravel API路由如何设计_Laravel构建RESTful API的路由最佳实践
Laravel怎么配置S3云存储驱动_Laravel集成阿里云OSS或AWS S3存储桶【教程】
上一篇:凡科网扫码登录失败应如何解决?
上一篇:凡科网扫码登录失败应如何解决?

