JS解决position:sticky的兼容性问题的方法


Posted in Javascript onOctober 17, 2017

在项目中有用到sticky的布局,可是由于兼容性问题,在安卓端没有很好的兼容,所以为了彻底解决这个问题只能写一个组件来解决这个麻烦的问题,这里为什么是组件而不是指令是因为,是有原因的,下面会讲到。

position:sticky的兼容性以及作用

Caniuse上显示sticky的兼容性如下:

JS解决position:sticky的兼容性问题的方法

Sticky的作用相当于relative和fixed的结合体,当修饰的目标节点再屏幕中时表现为relative,当要超出的时候是fixed的形式展现,因为这个特性,我们就可以来实现一个sticky的模拟效果。

sticky组件实现

template部分

<template>
  <div class="sticky" :style="getPosition">
    <div class="sticky-warp">
      <slot></slot>
    </div>
  </div>
</template>

代码解读:这里我使用了组件来实现,而不用指令来实现的原因是:指令虽然是无侵入性的,更方便使用,可是有一个弊端就是当修饰的节点fixed的时候会脱离文档流,会改变滚动的条的高度,如果仅仅是配合原生滚动条来实现是没问题的(当然这也会存在滚动过快的问题),可是由于是配合自定义滚动所以,采取这种折中的方式来实现。最外层是一个sticky层,判断浏览器是否支持sticky,不支持就使用relative来代替,这样也就不会改变浏览器高度的情况了,然后动态改变stick-warp层的postion来实现效果。

css部分

<style scoped lang="less" rel="stylesheet/less">
  .sticky {
    width: 100%;
    .sticky-warp {
      width: 100%;
      background: inherit;
      will-change: change;
      height: inherit;
      top: inherit;
    }
  }
</style>

代码解读:这里的warp层的背景色设置和sticky一致,这样过渡不会太生硬,高度和top都根据用户对外层sticky的自定义来实现,这样这部分简单用css就可以完成了。

JS部分

<script type="text/babel">
  export default {
    data () {
      return {}
    },
    computed: {
      getPosition(){
        var position = this.cssSupport('position', 'sticky') ? 'sticky' : 'relative';
        return 'position:' + position;
      }
    },
    props: {},
    beforeMount () {
    },
    mounted(){
      this.init();
    },
    deactivated(){
      if(this.cssSupport('position', 'sticky')) {
        return;
      }
      /*复位*/
      var elWarp = this.$el.querySelector('.sticky-warp');
      elWarp.position = 'absolute';
    },
    methods: {
      init(){
        if (this.cssSupport('position', 'sticky')) {
          return;
        }
        var el = this.$el, target = this.$el.parentNode,
            elWarp = this.$el.querySelector('.sticky-warp'),
            top = this.getNumberValue(document.defaultView.getComputedStyle(el).top);
        this.addScrollListen(target, (event)=> {
          if (el.getBoundingClientRect().top <= top) {
            elWarp.style.position = 'fixed';
          }
          if (el.getBoundingClientRect().top >= 0 && elWarp.style.position != 'absolute') {
            elWarp.style.position = 'absolute';
          }
        })
      },
      cssSupport: function (attr, value) {
        var element = document.createElement('div');
        if (attr in element.style) {
          element.style[attr] = value;
          return element.style[attr] === value;
        } else {
          return false;
        }
      },
      getNumberValue(pxValue){
        var value = String(pxValue).match(/^\-?\+?[0-9]+/g);
        return value ? Number(value) : undefined;
      },
      addScrollListen(target, cb){
        target.addEventListener('y-scroll', (event)=> {
          cb && cb(event);
        });
      }
    },
  }

 
</script>

代码解读:这里面主要先用cssSupport来判断一下浏览器的支持情况,然后通过多自定义滚动y-scroll事件的监听,监听top值的改变来实现sticky-warp层的fixed和absolute的转换。大概原理的思路及实现过程就是上面这样,对于自定义的滚动的github地址:https://github.com/yejiaming/scroll,sticky组件以及原生滚动下的指令参考的实现的github地址如下:https://github.com/yejiaming/sticky

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JavaScript的面向对象(一)
Nov 09 Javascript
jquery 1.4.2发布!主要是性能与API
Feb 25 Javascript
基于JQuery模仿苹果桌面的Dock效果(初级版)
Oct 15 Javascript
JavaScript中的small()方法使用详解
Jun 08 Javascript
JS实现三级折叠菜单特效,其它级可自动收缩
Aug 06 Javascript
js实现遍历含有input的table实例
Dec 07 Javascript
jQuery基础的工厂函数以及定时器的经典实例分析
May 20 Javascript
json的使用小结
Jun 08 Javascript
轻松掌握JavaScript单例模式
Aug 25 Javascript
node.js支持多用户web终端实现及安全方案
Nov 29 Javascript
vue-cli在 history模式下的配置详解
Nov 26 Javascript
原生js实现自定义滚动条
Jan 20 Javascript
JS实现div模块的截图并下载功能
Oct 17 #Javascript
bootstrap模态框嵌套、tabindex属性、去除阴影的示例代码
Oct 17 #Javascript
AngularJS 控制器 controller的详解
Oct 17 #Javascript
VUE前端cookie简单操作
Oct 17 #Javascript
javascript 判断用户有没有操作页面
Oct 17 #Javascript
vue-router 路由基础的详解
Oct 17 #Javascript
如何抽象一个Vue公共组件
Oct 17 #Javascript
You might like
Discuz!5的PHP代码高亮显示插件(黑暗中的舞者更新)
2007/01/29 PHP
php smarty模版引擎中变量操作符及使用方法
2009/12/11 PHP
去掉destoon资讯内容页keywords关键字自带的文章标题的方法
2014/08/21 PHP
php提供实现反射的方法和实例代码
2019/09/17 PHP
仅IE9/10同时支持script元素的onload和onreadystatechange事件分析
2011/04/27 Javascript
jBox 2.3基于jquery的最新多功能对话框插件 常见使用问题解答
2011/11/10 Javascript
javascript中普通函数的使用介绍
2013/12/19 Javascript
javascript生成随机大小写字母的方法
2014/02/20 Javascript
开源的javascript项目Kissy介绍
2014/11/28 Javascript
javascript委托(Delegate)blur和focus用法实例分析
2015/05/26 Javascript
JavaScript html5 canvas绘制时钟效果
2016/03/01 Javascript
AngularJS模板加载用法详解
2016/11/04 Javascript
HTML的select控件美化
2017/03/27 Javascript
基于JavaScript实现的快速排序算法分析
2017/04/14 Javascript
node中间层实现文件上传功能
2018/06/11 Javascript
Node+OCR实现图像文字识别功能
2018/11/26 Javascript
微信小程序自定义导航栏(模板化)
2019/11/15 Javascript
jQuery是用来干什么的 jquery其实就是一个js框架
2021/02/04 jQuery
python实现百度关键词排名查询
2014/03/30 Python
Python 文件管理实例详解
2015/11/10 Python
Python实现字典的遍历与排序功能示例
2017/12/23 Python
详解python中Numpy的属性与创建矩阵
2018/09/10 Python
python 对字典按照value进行排序的方法
2019/05/09 Python
python利用JMeter测试Tornado的多线程
2020/01/12 Python
Python 炫技操作之合并字典的七种方法
2020/04/10 Python
基于Python爬取搜狐证券股票过程解析
2020/11/18 Python
css3的@media属性实现页面响应式布局示例代码
2014/02/10 HTML / CSS
html5 canvas 实现光线沿不规则路径运动
2020/04/20 HTML / CSS
写出一个方法实现冒泡排序
2016/07/08 面试题
师范学院美术系毕业生自我鉴定
2014/01/29 职场文书
学生请假条格式
2014/04/11 职场文书
优秀班主任经验交流材料
2014/06/02 职场文书
关于清明节的演讲稿
2014/09/13 职场文书
大学军训心得体会800字
2016/01/11 职场文书
党员理论学习心得体会
2016/01/21 职场文书
Rhit高效可视化Nginx日志查看工具
2021/11/01 Servers