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 相关文章推荐
js字符串截取函数substr substring slice使用对比
Nov 27 Javascript
js复制网页内容并兼容各主流浏览器的代码
Dec 17 Javascript
js关于精确计算和数值格式化以及直接引js文件
Jan 28 Javascript
javascript中的__defineGetter__和__defineSetter__介绍
Aug 15 Javascript
jquery插件star-rating.js实现星级评分特效
Apr 15 Javascript
Bootstrap源码解读排版(1)
Dec 23 Javascript
angular ng-repeat数组中的数组实例
Feb 18 Javascript
微信小程序 跳转方式总结
Apr 20 Javascript
vue.js实现简单轮播图效果
Oct 10 Javascript
layui实现数据表格隐藏列的示例
Oct 25 Javascript
JS常见内存泄漏及解决方案解析
May 30 Javascript
javascript实现贪吃蛇游戏(娱乐版)
Aug 17 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
PHP 防注入函数(格式化数据)
2011/08/08 PHP
PHP 利用AJAX获取网页并输出的实现代码(Zjmainstay)
2012/08/31 PHP
使用php批量删除数据库下所有前缀为prefix_的表
2014/06/09 PHP
利用PHP函数计算中英文字符串长度的方法
2014/11/11 PHP
PHP 年月日的三级联动实例代码
2017/05/24 PHP
PHP获取数组中指定的一列实例
2017/12/27 PHP
jQuery.ajax 用户登录验证代码
2010/10/29 Javascript
jquery表单验证使用插件formValidator
2012/11/10 Javascript
JS使用replace()方法和正则表达式进行字符串的搜索与替换实例
2014/04/10 Javascript
ext中store.load跟store.reload的区别示例介绍
2014/06/17 Javascript
jQuery.trim() 函数及trim()用法详解
2015/10/26 Javascript
利用Angularjs中模块ui-route管理状态的方法
2016/12/27 Javascript
基于jQuery代码实现圆形菜单展开收缩效果
2017/02/13 Javascript
Node.js 8 中的 util.promisify的详解
2017/06/12 Javascript
vue元素实现动画过渡效果
2017/07/01 Javascript
vue elementUI table表格数据 滚动懒加载的实现方法
2019/04/04 Javascript
基于Vue3.0开发轻量级手机端弹框组件V3Popup的场景分析
2020/12/30 Vue.js
[01:01:04]2018DOTA2亚洲邀请赛 4.5 淘汰赛 OpTic vs TNC 第一场
2018/04/06 DOTA
python得到一个excel的全部sheet标签值方法
2018/12/10 Python
python实现文件助手中查看微信撤回消息
2019/04/29 Python
Python叠加两幅栅格图像的实现方法
2019/07/05 Python
Pytorch 中的optimizer使用说明
2021/03/03 Python
CSS3 清除浮动的方法示例
2018/06/01 HTML / CSS
CSS3 animation ? steps 函数详解
2019/08/30 HTML / CSS
CSS3实现图片抽屉式效果的示例代码
2019/11/06 HTML / CSS
美国在线眼镜店:GlassesShop
2018/11/15 全球购物
考试作弊检讨书大全
2014/02/18 职场文书
《蓝色的树叶》教学反思
2014/02/24 职场文书
2014年端午节活动方案
2014/03/11 职场文书
公司开业庆典策划方案
2014/06/04 职场文书
汽车技术服务与贸易专业求职信
2014/07/20 职场文书
校本研修个人总结
2015/02/28 职场文书
运动会加油稿50字
2015/07/21 职场文书
《学会看病》教学反思
2016/02/17 职场文书
MySQL连接控制插件介绍
2021/09/25 MySQL
错误码NET::ERR_CERT_DATE_INVALID证书已过期解决方法?
2022/07/07 数码科技