组件之路---固钉组件

固钉组件的作用是将页面元素固定在可视区域之内。

恩!是这样

需求

固钉的基本功能就是将元素固定在页面的特定位置,即使存在滚动条的情况下,固钉元素仍然可以固定在设定的位置。

这里位置固定所指的参考有两种情况:

  1. 元素相对窗口固定位置。
  2. 元素相对于父容器固定位置。

常规情况下,我们使用的是元素相对于窗口位置固定,这里直接使用fixed布局就可以了,但是对于第二种需求就不容易实现了,这也是固钉组件主要实现的功能。

预备知识

pageYOffset pageXOffset

pageYOffset pageXOffset是window的属性,表示整个页面滚动过的值,可以使用body元素的scrollTop属性替代。

scrollTop scrollLeft

scrollTop scrollLeft是Element的属性,表示一个具有属性的元素滚动过的值。

offsetTop offsetLeft

要想解释offsetTop 以及 offsetLeft的值,需要理解offsetParent的概念。
offsetParent可以返回距离当前元素最近的采用定位(position属性值为fixed、relative或者absolute)祖先元素。
如果祖先元素中没有采用定位的元素,则返回body对象。
offsetTop/offsetLeft返回值表示当前元素上边缘/左边缘距离offsetParent返回元素的距离的数值,单位是像素。

总结:scroll是与滚动相关的属性,offset是与offsetParent相关的属性值

innerHeight

innerHeight为window的属性,指窗口的大小(不包含工具条与滚动条)。

clientHeight

clientHeight这个属性是只读属性,对于没有定义CSS或者内联布局盒子的元素为0,同时它是元素内部的高度(单位像素),包含内边距,但不包括水平滚动条、边框和外边距。
clientHeight 可以通过 CSS height + CSS padding - 水平滚动条高度.

offsetHeight

在IE6,IE7,IE8以及最新的的FF, Chrome中,在元素上都是offsetHeight = clientHeight + 滚动条 + 边框。

scrollHeight

这个高度与滚动条无关,是内容的实际高度。

计算方式 :scrollHeight = topPadding + bottomPadding + 内容margix box的高度。

总结:clientHeight与scrollHeight与滚动条有关,前者与设置的height有关,后者与元素所占据的实际高度有关

fixed布局

fixed布局是我们通常采用的实现元素固定在窗口的特定位置,如下图所示:


image

但是如果我们想实现基于任意父容器的固钉呢?即使其固定在父容器的指定位置,而不是单纯的固定在窗口的指定位置,如下图所示:


fixedToContainer.gif

实现原理

其实实现第二种需求的固钉仍然是基于fixed布局的,只不过我们这里加入的事件监听,动态的设置元素的top/bottom等值,以在视觉效果上实现相对于父元素的位置固定。

事件列表

events = [
    'resize',
    'scroll',
    'touchstart',
    'touchmove',
    'touchend',
    'pageshow',
    'load',
  ];

固钉组件组件要监听如上列表中列出的事件,由以上事件触发位置更新。

注意:这里监听事件的元素应该是固钉的容器元素target,若不指定target,会默认为body。

位置更新

以实现距离容器组件顶部为settingTop px为例,说明何时进行位置更新,以及如何位置更新。

const scrollTop = getScrollTop(targetNode);
const elemOffset = getOffset(affixNode, targetNode);
//elemOffset表示固钉的位置,包括父容器滚动过的值
const targetRect = getTargetRect(targetNode);
//targetRect是基于getBoundingClientRect得到的元素位置信息
//getBoundingClientRect方法返回元素的大小及其相对于视口的位置

if (scrollTop > elemOffset.top - settingTop) {
      // Fixed Top
      const width = elemOffset.width;
      const top = targetRect.top + settingTop;
      //即根据父容器的位置和设置的参数确定固钉的实际位置。
      this.setAffixStyle(e, {
        position: 'fixed',
        top,
        left: targetRect.left + elemOffset.left,
        width,
      });
}

这里有一个问题,即该如何去理解判断条件呢?

scrollTop > elemOffset.top - settingTop

其实可以将判断条件改写为:

elemOffset.top - scrollTop < settingTop

即页面向上滚动之后elemOffset.top - scrollTop(即固钉相对于父元素顶部的距离)小于预设值settingTop,发生位置更新。

同理,如果设置的参数是settingBottom,也可以以同样的思路分析。

总结

固钉实现的思路仍然是基于fixed布局,只不过我们为了实现相对于任意父元素的位置固定,引入了事件监听以及位置更新。理解位置更新的机制,关键是理解本文中涉及到的各种距离到底指的是什么。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容

  • Element对象对应网页的HTML标签元素。每一个HTML标签元素,在DOM树上都会转化成一个Element节点...
    许先生__阅读 1,793评论 0 2
  • 问答题47 /72 常见浏览器兼容性问题与解决方案? 参考答案 (1)浏览器兼容问题一:不同浏览器的标签默认的外补...
    _Yfling阅读 13,725评论 1 92
  • 前言 CSSOM全称CSS对象模型,涉及两部分内容,第一部分和操作样式表相关,第二部分和元素尺寸相关,本文介绍第二...
    江枫阅读 2,971评论 1 10
  • 个人博客:https://yeaseonzhang.github.io 花了半个多月的时间,终于又把“JS红宝书”...
    Yeaseon阅读 11,465评论 9 52
  • 小A是一名客服,工作内容除了正常解答业务知识,还需要处理各种投诉。 年初,小A得知公司年终评选客服标兵,...
    积极向上的桃子阅读 384评论 0 0