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 相关文章推荐
pjblog中的UBBCode.js
Apr 25 Javascript
用示例说明filter()与find()的用法以及children()与find()的区别分析
Apr 26 Javascript
JavaScript给按钮绑定点击事件(onclick)的方法
Apr 07 Javascript
js判断手机号运营商的方法
Oct 23 Javascript
JavaScript学习笔记之数组随机排序
Mar 23 Javascript
AngularJS基础 ng-mouseleave 指令详解
Aug 02 Javascript
Sublime Text新建.vue模板并高亮(图文教程)
Oct 26 Javascript
Vuex的actions属性的具体使用
Apr 14 Javascript
vue实现路由懒加载及组件懒加载的方式
Jun 11 Javascript
详解基于原生JS验证表单组件xy-form
Aug 20 Javascript
js实现弹幕墙效果
Dec 10 Javascript
详细聊聊浏览器是如何看闭包的
Nov 11 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
PHPWind与Discuz截取字符函数substrs与cutstr性能比较
2011/12/05 PHP
php设计模式之单例模式使用示例
2014/01/20 PHP
WordPress中缩略图的使用以及相关技巧
2015/11/24 PHP
CodeIgniter配置之SESSION用法实例分析
2016/01/19 PHP
php mysql PDO 查询操作的实例详解
2017/09/23 PHP
用js重建星际争霸
2006/12/22 Javascript
JS实现仿京东淘宝竖排二级导航
2014/12/08 Javascript
浅谈Javascript线程及定时机制
2015/07/02 Javascript
基于JS实现移动端访问PC端页面时跳转到对应的移动端网页
2020/12/24 Javascript
浅谈angularjs $http提交数据探索
2017/01/20 Javascript
PHP实现记录代码运行时间封装类实例教程
2017/05/08 Javascript
es6中的解构赋值、扩展运算符和rest参数使用详解
2017/09/28 Javascript
JS使用tofixed与round处理数据四舍五入的区别
2017/10/25 Javascript
初探js和简单隐藏效果的实例
2017/11/23 Javascript
基于Bootstrap实现城市三级联动
2017/11/23 Javascript
JS实现全屏预览F11功能的示例代码
2018/07/23 Javascript
Vue创建头部组件示例代码详解
2018/10/23 Javascript
基于vue+echarts 数据可视化大屏展示的方法示例
2020/03/09 Javascript
JavaScript创建表格的方法
2020/04/13 Javascript
如何在 Vue 中使用 JSX
2021/02/14 Vue.js
[16:56]heroes英雄教学 司夜刺客
2014/09/18 DOTA
[10:28]2018DOTA2国际邀请赛寻真——VGJ.S寻梦之路
2018/08/15 DOTA
基于DataFrame筛选数据与loc的用法详解
2018/05/18 Python
解决使用export_graphviz可视化树报错的问题
2019/08/09 Python
基于python的itchat库实现微信聊天机器人(推荐)
2019/10/29 Python
python使用梯度下降算法实现一个多线性回归
2020/03/24 Python
Python matplotlib图例放在外侧保存时显示不完整问题解决
2020/07/28 Python
HTML5 3D书本翻页动画的实现示例
2019/08/28 HTML / CSS
SQL SERVER面试资料
2013/03/30 面试题
党员入党表决心的话
2014/03/11 职场文书
介绍信格式
2015/01/30 职场文书
党员自我评价范文2015
2015/03/03 职场文书
2015年护士工作总结范文
2015/03/31 职场文书
Navicat连接MySQL错误描述分析
2021/06/02 MySQL
OpenCV-Python 实现两张图片自动拼接成全景图
2021/06/11 Python
源码安装apache脚本部署过程详解
2022/09/23 Servers