zoukankan      html  css  js  c++  java
  • jQuery.stickUp插件重构

      stickUp插件用于实现固定菜单栏效果,原理很简单,说白了就是监听document的scroll事件,滚动到特定值时,将特定元素的position设置为fixed,核心代码如下:
     
     1  $(document).on('scroll', function() {
     2                 varscroll = parseInt($(document).scrollTop());
     3                 if (menuSize != null) {
     4                     for (var i = 0; i < menuSize; i++) {
     5                         contentTop[i] = $('#' + content[i] + '').offset().top;
     6 
     7                         function bottomView(i) {
     8                             contentView = $('#' + content[i] + '').height() * .4;
     9                             testView = contentTop[i] - contentView;
    10                             //console.log(varscroll);
    11                             if (varscroll > testView) {
    12                                 $('.' + itemClass).removeClass(itemHover);
    13                                 $('.' + itemClass + ':eq(' + i + ')').addClass(itemHover);
    14                             } else if (varscroll < 50) {
    15                                 $('.' + itemClass).removeClass(itemHover);
    16                                 $('.' + itemClass + ':eq(0)').addClass(itemHover);
    17                             }
    18                         }
    19                         if (scrollDir == 'down' && varscroll > contentTop[i] - 50 && varscroll < contentTop[i] + 50) {
    20                             $('.' + itemClass).removeClass(itemHover);
    21                             $('.' + itemClass + ':eq(' + i + ')').addClass(itemHover);
    22                         }
    23                         if (scrollDir == 'up') {
    24                             bottomView(i);
    25                         }
    26                     }
    27                 }
    28 
    29 
    30 
    31                 if (vartop < varscroll + topMargin) {
    32                     $('.stuckMenu').addClass('isStuck');
    33                     $('.stuckMenu').next().closest('div').css({
    34                         'margin-top': stickyHeight + stickyMarginB + currentMarginT + 'px'
    35                     }, 10);
    36                     $('.stuckMenu').css("position", "fixed");
    37                     $('.isStuck').css({
    38                         top: '0px'
    39                     }, 10, function() {
    40 
    41                     });
    42                 };
    43 
    44                 if (varscroll + topMargin < vartop) {
    45                     $('.stuckMenu').removeClass('isStuck');
    46                     $('.stuckMenu').next().closest('div').css({
    47                         'margin-top': currentMarginT + 'px'
    48                     }, 10);
    49                     $('.stuckMenu').css("position", "relative");
    50                 };
    51 
    52             });
    View Code
      但是,在实际使用过程中,还是发现诸多不便,
    • 它只支持最后一次调用(因为是使用闭包实现的变量存储,但每次init都基于同样一套变量)
    • 存在一些未经声明的变量调用(即全局变量,这可是很不好的编程习惯啊)
    • 存在一些不必要的函数声明,导致一些不必要的性能损耗(比如上述代码中的bottomView函数)
    • 不支持回调函数,无法支持比较复杂的应用
    • 单页网站时,在页面滚动到parts参数指定的块时,会给对应的菜单块加itemHover类(请参考http://lirancohen.github.io/stickUp/),parts是一个额外指定的参数,而parts中每一个id对应的菜单项又是基于parts参数的顺序的,这是一种不稳定结构(语文老师死得早,凑合着看吧
        stickUp原项目在github中很久没有更新了,所以我决定fork出一个分支,然后自己重构stickUp插件,我的项目地址是:https://github.com/VanMess/stickUp,有兴趣的童鞋可以clone下来看看,核心文件的代码只有150多行,结构也比较清晰,大家可以看看,有什么问题请联系我,交流交流。。。。当然,如果哪位大神能提出一些意见就更好了。
          新的stickUp代码主要分三个部分:Context类、Context._init_ 初始化函数、Context.onScroll 滚动处理函数。
        Context是一个上下文数据结构,用于记录每次调用的上下文信息,这样就解决了上面的第1个问题,代码如下:
        
     1 var Context = function() {},
     2         _ctxList = {},
     3         lastScrollTop = 0;
     4     Context.prototype = {
     5         dataProperty: 'data-menu',
     6         selector: '',
     7         itemClass: '',
     8         itemHover: '',
     9         jqDom: null,
    10         menuItems: [],
    11         region: 'top',
    12         height: 0,
    13         parentMarginTop: 0,
    14         top: 0,
    15         marginTop: 0,
    16         marginBottom: 0,
    17         beforeStick: null,
    18         afterStick: null,
    19         beforeUnstick: null,
    20         afterUnstick: null
    21 };
    View Code
      具体每一项的含义、用法,建议大家可以看看源码。
        Context._init_ 是一个初始化函数,一个工厂,接受一个option参数,并将之转换为一个Context实例,注意,这里使用了_ctxList 变量来存储历史以来所有的上下文信息,代码如下:
     
    View Code
      最后,是Context.prototype.onScroll 类,用于处理页面滚动事件,是整个stickUp的核心所在,代码如下:
     
    onScroll: function(scrollDir, varscroll) {
                var contentView = null,
                    testView = null,
                    _me = this;
    
                // 计算并给适当元素添加 itemHover 类
                if ( !! _me.menuItems && _me.menuItems.length > 0) {
                    var offset = null,
                        contentTop = 0,
                        tmp_menuTarget = null;
                    for (var i = 0; i < _me.menuItems.length; i++) {
                        tmp_menuTarget = $('#' + $(_me.menuItems[i]).attr(_me.dataProperty));
                        offset = tmp_menuTarget.offset();
                        contentTop = !! offset ? offset.top : 0;
    
                        // 之前這裡定義了一個bottomView
                        // 会在每次执行这个地方的时候都去创建一个函数
                        // 实际上是很没必要的性能损耗,所以这里将代码移动下面
                        if (scrollDir == 'down' &&
                            varscroll > contentTop - 50 &&
                            varscroll < contentTop + 50) {
                            _me.jqDom.find('.' + _me.itemClass).removeClass(_me.itemHover);
                            _me.jqDom.find('.' + _me.itemClass + ':eq(' + i + ')').addClass(_me.itemHover);
                        }
                        if (scrollDir == 'up') {
                            // 这里就是原来的bottomView代码
                            contentView = tmp_menuTarget.height() * 0.4;
                            testView = contentTop - contentView;
                            if (varscroll > testView) {
                                _me.jqDom.find('.' + _me.itemClass).removeClass(_me.itemHover);
                                _me.jqDom.find('.' + _me.itemClass + ':eq(' + i + ')').addClass(_me.itemHover);
                            } else if (varscroll < 50) {
                                _me.jqDom.find('.' + _me.itemClass).removeClass(_me.itemHover);
                                _me.jqDom.find('.' + _me.itemClass + ':eq(0)').addClass(_me.itemHover);
                            }
                        }
                    }
                }
    
                // 固定菜单栏目,使之固定(fixed)
                if (_me.top < varscroll + _me.marginTop) {
                    if ( !! _me.beforeStick) _me.beforeStick.call(_me);
                    _me.jqDom.addClass('isStuck');
                    if ( !! _me.afterStick) _me.afterStick.call(_me);
                    _me.jqDom.next().closest('div').css({
                        'margin-top': _me.height + _me.marginBottom + _me.parentMarginTop + 'px'
                    }, 10);
                    _me.jqDom.css("position", "fixed");
                    _me.jqDom.css({
                        top: '0px'
                    }, 10);
                };
    
                // 菜單欄目,使之不固定(relative)
                if (varscroll + _me.marginTop < _me.top) {
                    if ( !! _me.beforeUnstick) _me.beforeUnstick.call(_me);
                    _me.jqDom.removeClass('isStuck');
                    if ( !! _me.afterUnstick) _me.afterUnstick.call(_me);
                    _me.jqDom.next().closest('div').css({
                        'margin-top': _me.parentMarginTop + 'px'
                    }, 10);
                    _me.jqDom.css("position", "relative");
                };
            }
    View Code
    后记:一直想做一个自己的开源项目,不过还没想清楚要做什么,所以想着先拿别人的来重构、优化,这次使用stickUp是看中它的小(下次想修改百度的ECharts)。stickUp还不是很成熟,但根据我的测试在多个浏览器下都不存在大问题,欢迎大家使用,有什么问题请尽管联系我
    另外,看在我辛苦的份上,就麻烦大家留个言鼓励鼓励吧,谢谢
    最后附上源码:https://github.com/VanMess/stickUp
     
     
  • 相关阅读:
    LeetCode 977 有序数组的平方
    LeetCode 24 两两交换链表中的节点
    LeetCode 416 分割等和子集
    LeetCode 142 环形链表II
    LeetCode 106 从中序与后序遍历序列构造二叉树
    LeetCode 637 二叉树的层平均值
    LeetCode 117 填充每个节点的下一个右侧节点
    LeetCode 75 颜色分类
    redhat 7.4 挂载ntfs格式的u盘并且使用
    redhat 查看CPU frequency scaling(CPU频率缩放)
  • 原文地址:https://www.cnblogs.com/vans/p/3789416.html
Copyright © 2011-2022 走看看