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 相关文章推荐
jquery插件 cluetip 关键词注释
Jan 12 Javascript
jquery click([data],fn)使用方法实例介绍
Jul 08 Javascript
JQUERY 获取IFrame中对象及获取其父窗口中对象示例
Aug 19 Javascript
jqGrid增加时--判断开始日期与结束日期(实例解析)
Nov 08 Javascript
javascript实现汉字转拼音代码分享
Apr 20 Javascript
jQuery针对input的class属性写了多个值情况下的选择方法
Jun 03 Javascript
微信小程序 数据绑定详解及实例
Oct 25 Javascript
B/S(Web)实时通讯解决方案分享
Apr 06 Javascript
javascript帧动画(实例讲解)
Sep 02 Javascript
vue-router 手势滑动触发返回功能
Sep 30 Javascript
node.js中npm包管理工具用法分析
Feb 14 Javascript
Vue + Element-ui的下拉框el-select获取额外参数详解
Aug 14 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
ThinkPHP中__initialize()和类的构造函数__construct()用法分析
2014/11/29 PHP
Zend Framework教程之Zend_Form组件实现表单提交并显示错误提示的方法
2016/03/21 PHP
PHP QRCODE生成彩色二维码的方法
2016/05/19 PHP
javascript动态添加表格数据行(ASP后台数据库保存例子)
2010/05/08 Javascript
多个表单中如何获得这个文件上传的网址实现js代码
2013/03/25 Javascript
js获取某月的最后一天日期的简单实例
2013/06/22 Javascript
js和as的稳定传值问题解决
2013/07/14 Javascript
js获取 type=radio 值的方法
2014/05/09 Javascript
点击A元素触发B元素的事件在IE8下会识别成A元素
2014/09/04 Javascript
JS+CSS实现仿新浪微博搜索框的方法
2015/02/24 Javascript
jQuery源码分析之Callbacks详解
2015/03/13 Javascript
原生JS和JQuery动态添加、删除表格行的方法
2015/05/28 Javascript
简述JavaScript对传统文档对象模型的支持
2015/06/16 Javascript
jQuery.Validate表单验证插件的使用示例详解
2017/01/04 Javascript
微信小程序 图片宽度自适应的实现
2017/04/06 Javascript
vue 将页面公用的头部组件化的方法
2017/12/18 Javascript
AjaxUpLoad.js实现文件上传
2018/03/05 Javascript
微信自定义分享链接信息(标题,图片和内容)实现过程详解
2019/09/04 Javascript
python实现分析apache和nginx日志文件并输出访客ip列表的方法
2015/04/04 Python
Python实现高效求解素数代码实例
2015/06/30 Python
Python通过matplotlib画双层饼图及环形图简单示例
2017/12/15 Python
Python 导入文件过程图解
2019/10/15 Python
python:批量统计xml中各类目标的数量案例
2020/03/10 Python
Django Path转换器自定义及正则代码实例
2020/05/29 Python
如何在scrapy中捕获并处理各种异常
2020/09/28 Python
VICHY薇姿英国官网:全球专业敏感肌护肤领先品牌
2017/07/04 全球购物
戴森台湾线上商城:Dyson Taiwan
2018/05/21 全球购物
诗普兰迪官方网站:Splendid
2018/09/18 全球购物
MADE法国:提供原创设计师家具
2018/09/18 全球购物
经典c++面试题二
2015/08/14 面试题
单位提档介绍信
2014/01/17 职场文书
大班上学期个人总结
2015/02/13 职场文书
2015年中秋晚会主持稿
2015/07/30 职场文书
高三化学教学反思
2016/02/22 职场文书
redis复制有可能碰到的问题汇总
2022/04/03 Redis
html中两种获取标签内的值的方法
2022/06/10 HTML / CSS