这里有新鲜出炉的 Javascript 教程,程序狗速度看过来!
Javascript 是一种由 Netscape 的 LiveScript 发展而来的原型化继承的基于对象的动态类型的区分大小写的客户端脚本语言,主要目的是为了解决服务器端语言,比如 Perl,遗留的速度问题,为客户提供更流畅的浏览效果。
sticky 组件,通常应用于导航条或者工具栏,当网页在某一区域滚动的时候,将导航条或工具栏这类元素固定在页面顶部或底部,方便用户快速进行这类元素提供的操作
sticky 组件,通常应用于导航条或者工具栏,当网页在某一区域滚动的时候,将导航条或工具栏这类元素固定在页面顶部或底部,方便用户快速进行这类元素提供的操作。
在这篇文章 Sticky 组件的改进实现提供了一个改进版的 sticky 组件,并将演示效果应用到了自己的博客。有了类似 sticky 的这种简单组件,我们就可以在利用它开发更丰富的效果,比如本文要介绍的 tab 导航和滚动导航。实现简单,演示效果如下:
tab 导航(对应 tab-sticky.html):
滚动导航(对应 nav-scroll-sticky.html):
1. tab 导航的实现
tab 导航的需求是:在点击导航项的时候,除了切换 tab 内容,还要控制滚动,将要显示的 tab 内容置顶,并且要刚好显示在 sticky 元素的下边。由于 demo 是用 bootstrap 做的,bootstrap 提供的 tab 组件非常简单好用,我们可以在 tab 组件提供的 shown.bs.tab 的事件回调里做滚动控制处理,所以这个效果实现起来比较容易:
- <script>
- var $target = $('#target');
- new Sticky('#sticky', {
- unStickyDistance: 60,
- target: $target,
- wait: 1,
- isFixedWidth: false,
- getStickyWidth: function($elem) {
- return $elem.parent()[0].offsetWidth;
- }
- });
- $('a[data-toggle="tab"]').on('shown.bs.tab',
- function(e) {
- window.scrollTo(0, $target[0].getBoundingClientRect().top + getPageScrollTop() + 1);
- });
- function getPageScrollTop() {
- return window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
- }
- </script>
html 结构:
2. 滚动导航实现
滚动导航相对麻烦一些,tab 组件里面,只会显示与当前激活的 tab 项对应的 tab 内容,而滚动导航里面,要导航的所有内容都是已经在页面中渲染完毕的,它的需求是:
1)点击导航项的时候,控制页面滚动,自动将与点击的导航项对应的内容置顶显示,并且要刚好显示在 sticky 元素的下边;
2)页面滚动的时候,根据当前显示的导航内容自动给相应的导航项添加 active 样式。
尽管听起来复杂,但是 demo 中的实现还是比较容易:
- <script>
- var $sticky = $('#sticky');
- var $target = $('#target');
- new Sticky($sticky, {
- unStickyDistance: 60,
- target: $target,
- wait: 1,
- isFixedWidth: false,
- getStickyWidth: function($elem) {
- return $elem.parent()[0].offsetWidth;
- }
- });
- var offsetTop = 60;
- //实现点击tab项自动滚动到导航内容的效果
- $sticky.on('click', 'a',
- function(e) {
- e.preventDefault();
- var $this = $(e.currentTarget);
- var $parent = $this.parent();
- if ($parent.hasClass('active')) return;
- $sticky.find('li.active').removeClass('active');
- $parent.addClass('active');
- var target = $this.data('target') || $this.attr('href');
- var $target = $(target);
- window.scrollTo(0, Math.floor($target[0].getBoundingClientRect().top) + getPageScrollTop() - offsetTop);
- });
- /**
- * Math.floor是解决rect.top或rect.bottom带小数问题
- */
- //实现滚动时根据当前显示的导航内容自动给相应的导航项添加active样式
- $(window).scroll(throttle(function() {
- var $curItem = $sticky.find('a').filter('[href=' + getCurTarget() + ']');
- var $parent = $curItem.parent();
- if ($parent.hasClass('active')) return;
- //最后的blur是为了去掉:active及:focus伪类的样式
- $sticky.find('li.active').removeClass('active').find('a').trigger('blur');
- $parent.addClass('active');
- },
- 1));
- //获取当前显示的导航内容元素的id
- function getCurTarget() {
- for (var targets = ['#First', '#Second', '#Third'], i = 0, l = targets.length; i < l; i++) {
- var curRect = $(targets[i])[0].getBoundingClientRect();
- if (Math.floor(curRect.top) <= offsetTop && Math.floor(curRect.bottom) > offsetTop) {
- return targets[i];
- }
- }
- return targets[0];
- }
- function getPageScrollTop() {
- return window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
- }
- //这个函数在实际工作中是应该抽出来的,否则sticky.js里面还有一份重复的
- function throttle(func, wait) {
- var timer = null;
- return function() {
- var self = this,
- args = arguments;
- if (timer) clearTimeout(timer);
- timer = setTimeout(function() {
- return typeof func === 'function' && func.apply(self, args);
- },
- wait);
- }
- }
- </script>
html 结构:
3. 总结
本文结合 sticky 组件,提供了 2 种导航效果实现,兼容 IE9+,firefox 以及 chrome,感兴趣可以下载源码再去详细了解。在实现 tab 导航的时候,因为有 bs 的 tab 组件所以实现起来非常容易,也没有必要把 sticky 跟 tab 组件再封装起来形成一个新组件,毕竟效果的实现代码已经比较简单了。在实现滚动导航的时候,因为没有用 tab 组件,所以滚动导航的那两个需求点都是单独实现的,在实际情况中,这两个功能可以封装成 2 个独立的组件或者 1 个组件,这样就能把实现代码写的像 tab 导航那样简单,不过本文没有再深入去介绍这两个组件的写法,因为这不是本文主要想介绍的内容,虽然我很想这么做,后续肯定会再写博客来介绍这两个组件,简单的东西不造一下轮子,简直是浪费机会。在实现这两个效果的时候,也有 2 点收获:
1)firefox 以及 IE,先让网页,然后再刷新,虽然网页还会显示在刷新的位置,但是不会触发 scroll 事件,所以今后做 scroll 相关的组件,一定在组件初始化的时候主动掉一次 scroll 相关的回调;
2)getBoundingClientRect 返回的 rect 对象相关的值,在 IE 和 firefox 下,都可能是小数,比如 60.2222299999,这样的数,在进行判断的时候可能会跟预期情况不符,导致一些意外的 BUG,如果不是特别严谨的话,可以用 Math.floor 对这些值进行取整,然后再用来计算或者判断。比如滚动导航实现中,rect.top 的值 60.2222299999,offsetTop 的值是 60,期望是 curRect.top <= offsetTop 这个条件能够成立,因为小数的原因,所以它不成立。
来源: http://www.phperz.com/article/17/0718/266620.html