此为vue.js
版滚动导航组件,实现
- 滚动时,根据滚动距离判断当前内容所属哪个导航
- 点击导航,页面滚动到内容对应位置
- 可控制导航栏是否吸附固定,如吸顶效果,即滚动一定距离后,导航栏固定起来,不会被滚动出可视区域
- 可用在页面任何位置上,不一定是顶部导航这种简单应用哦,可以复杂型应用
- 在浏览器支持下,可以采用
position: sticky
方式实现固定
在线demo示例,可进入demo中浏览实际效果,但是demo是用纯js写,可忽略代码部分,具体要用这个类库的使用方法请继续阅读下文。
具体深度解释该组件的一个开发思路,可看此文章滚动导航+吸顶合并方案(含stikcy详解)
该插件不包含vue.js
的引入,请你自行引入vue.js
<script>
方式直接引入lib/vue-scroll-nav.umd.min.js
,如:
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="node_modules/vue-scroll-nav/lib/vue-scroll-nav.umd.min.js"></script>
这样就可以在Vue
应用里直接使用<Scroll-Nav>
标签了。
npm方式:
npm i vue-scroll-nav
引入该插件之后,得注册组件
import Vue from 'vue';
import scrollNav from 'vue-scroll-nav';
Vue.use(scrollNav);
这是一个简单的使用情况
<Scroll-Nav
ref="scrollNav"
:menu="[
{ label: '导航1', checked: true },
{ label: '导航2' },
{ label: '导航3' }
]"
:height="52"
relativeName="html">
<div>导航1内容</div>
<div>导航2内容</div>
<div>导航3内容</div>
</Scroll-Nav>
导航栏的选项就是menu
属性的数组选项,导航栏的高度为52px
,引发滚动的容器是html
(即滚动条在html
上),导航选项对应的内容就是里面的三个div
。
上面就实现了,当滚动条进行滚动时,会根据滚动的距离,判断导航栏是否被固定住,以及当前滚动的位置对应哪个导航选项的内容;点击导航选项也会跳转到对应内容开头处。
插件提供了足够的属性,让你针对不同的复杂情况来自定义它的行为。
menu
:必填。导航栏选项,值为数组,元素固定格式为{label: 'xxx', checked: false}
,label
为导航的名字,checked
是来控制导航被选中样式的height
:导航栏的高度,一般是指未固定前的高度,值为Number
orString
类型,传入数字类型时,默认为px
默认值为52px
。width
:导航栏的宽度,一般是指未固定前的宽度,值为Number
orString
类型,传入数字类型时,默认为px
;默认值为100%
。fixedHeight
:导航栏的高度,指固定之后的高度,值为Number
orString
类型,传入数字类型时,默认为px
。导航栏固定后的高度默认按照设置了的height
属性fixedWidth
:导航栏的宽度,指固定之后的宽度,值为Number
orString
类型,传入数字类型时,默认为px
。导航栏固定后的宽度默认按照设置了的width
属性relativeName
:滚动条所在元素的名字(可类名id名元素名等元素标识),如果是在html
上,请直接传'html'
,值为String
类型,默认值为html
extraFixed
:对滚动条滚动的高度做运算的值,由于滚动区域的offsetParent可能跟导航栏的offsetParent不一样,会存在差值,所以判断导航栏是否达到固定条件是,需要对滚动区域的scrollTop结合该值做运算,值为Number
类型,默认值是0
。该属性可能不好理解,可看开头说的文章,了解具体情况。extraScroll
:用来对滚动时哪个导航需要被激活,做额外的偏差值运算判断,在不吸顶的情况下,导航指定的内容只要滚动到滚动容器顶部就算到了该内容了的导航了,即滚动了【内容的offsetTop】的距离,但是吸顶之后,只要滚动到吸顶导航栏底部就算到了指定导航内容了,所以相当于只要滚动【内容的offsetTop - 吸顶导航栏的高度】的距离就会到达临界值。转换成公式来理解,c代表导航内容的offsetTop,s代表滚动的距离,吸顶导航栏高度为h。只要滚动距离大于等于上面说的临界值,即肯定到达了对应导航。因此公式为: s >= c - h, 即 s + h >= c 时,到达条件成立,因此滚动容器的scrollTop都要加上h,才是拿来判断的值。当然上面说的只是一般的情况,还有滚动容器不是导航对应内容的offsetParent的情况,则需要加减【其他偏差值】,如padding等,所以这里的extraScroll就是表示这些【其他偏差值】,一般情况是跟上面的extraFixed等值的,这里我没有沿用extraFixed是因为,提供更多可能性给用户,有些用户可能不恰好就是用临界情况来区分内容落到哪个导航上,所以提供该值,让可以根据实际情况进行传值。但是不设置该值时,会默认沿用extraFixed的值。了解具体情况。needFixed
:是否需要固定导航栏,如吸顶情况。值为Boolean
类型,默认是true
。top
:导航栏固定之后的top值,值为Number
,String
类型,默认是0
。right
:导航栏固定之后的right值,值为Number
,String
类型,默认是auto
。left
:导航栏固定之后的left值,值为Number
,String
类型,默认是auto
。bottom
:导航栏固定之后的bottom值,值为Number
,String
类型,默认是auto
。color
:导航栏被选中的颜色,包括文字颜色和border-bottom
颜色。值为String
类型,默认是#387af6
。useSticky
:在浏览器支持的情况下,是否采用position:sticky
的方式实现导航栏固定。值为Boolean
类型,默认是true
。提供该值,主要是考虑到,如果页面的结构十分复杂,层级很多,有些情况下是无法使用sticky
或者说不方便计算实现sticky
的阈值时,就关闭该实现方式吧。stickyTop
:在实现sticky
方式下,导航栏固定之后的top值,值为Number
,String
类型,如果不设置该值,默认跟随top
值。stickyLeft
:在实现sticky
方式下,导航栏固定之后的left值,值为Number
,String
类型,如果不设置该值,默认跟随left
值。stickyRight
:在实现sticky
方式下,导航栏固定之后的right值,值为Number
,String
类型,如果不设置该值,默认跟随right
值。stickyBottom
:在实现sticky
方式下,导航栏固定之后的bottom值,值为Number
,String
类型,如果不设置该值,默认跟随bottom
值。useAnimation
:当点击菜单,切换到不同的内容,是否启用过渡动画效果(浏览器支持的情况下)。值为Boolean
类型,默认是true
。
该组件暴露出一个名为calcTop
的方法。主要是用来当页面内容发生变化,可能会引起各项内容的宽高发生变化,导致实际获取的导航栏和导航内容宽高发生变化,进而引起offsetTop
的变化。
该组件在不支持sticky
的浏览器里,会采用传统的监听scroll
事件,利用滚动距离和各项内容的offsetTop
进行比较判断。
因为,当你的内容发生变化后(如发送请求加载数据,改变浏览器页面大小等),你需要手动调用calcTop
方法,及时更新最新的offsetTop
值。
this.$refs.scrollNav.calcTop();
默认是只会计算导航所对应内容的offsetTop
,如果你需要计算导航栏的话,那么要传true
this.$refs.scrollNav.calcTop(true);
该方法可以告诉你,浏览器支持position: sticky
的情况,返回值为浏览器支持的sticky
值,即有前缀还是没前缀,抑或返回''
,如果返回空字符串,那么就是代表浏览器不支持sticky
该组件或许还存在不足之处,或者你的使用场景更广阔,如果你有兴趣的话,可以一起努力完善这个组件。期待你的加入
有问题,也欢迎提出。