Bootstrap滚动监听组件scrollspy.js使用方法详解

其实滚动监听使用的情况还是很多的,比如导航居于右侧,当主题内容滚动某一块的时候,右侧导航对应的要高亮。

实现功能

1、当滚动区域内设置的hashkey距离顶点到有效位置时,就关联设置其导航上的指定项 2、导航必须是 .nav > li > a 结构,并且a上href或data-target要绑定hashkey 3、菜单上必须有.nav样式 4、滚动区域的data-target与导航父级Id(一定是父级)要一致。

rush:xhtml;">

ibe

One的具体内容
One的具体内容
One的具体内容
One的具体内容
One的具体内容
One的具体内容

two

One的具体内容
One的具体内容
One的具体内容
One的具体内容
One的具体内容
One的具体内容

three

One的具体内容
One的具体内容
One的具体内容
One的具体内容
One的具体内容
One的具体内容

下面来看一下实现的具体代码,原理:当滚动容器内的hashkey位置距离容器顶部只有 offset设置的值,就会设置导航中对应的href高亮。

ScrollSpy构造函数

首先新建一个构造函数,如下:

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的值

<div class="jb51code">
<pre class="brush:js;">
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来获取

rush:js;"> if (!$.isWindow(this.$scrollElement[0])) { offsetMethod = 'position' offsetBase = this.$scrollElement.scrollTop() }

2.根据导航上的hashkey来遍历获取 滚动区域内的hashkey对应的offset值:

rush:js;"> 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,b) { return a[0] - b[0] })

.each(function () {
that.offsets.push(this[0])
that.targets.push(this[1])
})

process方法

滚动条事件触发函数,用于计算当前需要高亮那个导航菜单

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.获取滚动容器已滚动距离:

rush:js;"> var scrollTop = this.$scrollElement.scrollTop() + this.options.offset

2.滚动容器可以滚动的最大高度:

rush:js;"> var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height()

3.设置滚动元素逻辑,给当前匹配元素添加高亮:

= offsets[i] && (offsets[i + 1] === undefined || scrollTop < offsets[i + 1]) && this.activate(targets[i]) }

active方法

设置指定的导航菜单高亮

rush:js;"> 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方法

清除所有高亮菜单

rush:js;"> ScrollSpy.prototype.clear = function () { $(this.selector) .parentsUntil(this.options.target,'.active') .removeClass('active') }

源码

// SCROLLSPY CLASS DEFINITION
// ==========================

function ScrollSpy(element,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,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);

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程之家。

相关文章

Bootstrip HTML 查询搜索常用格式模版 &lt;form class=&...
如何在按钮上加红色数字 您可以使用Bootstrap的badge组件来在...
要让两个按钮左右排列,你可以使用 Bootstrap 的网格系统将它...
是的,可以将status设置为布尔类型,这样可以在前端使用复选...
前端工程师一般用的是Bootstrap的框架而不是样式,样式一般自...
起步导入:<linkrel="stylesheet"href="b...