在項目中有用到sticky的佈局,但是因爲兼容性問題,在安卓端沒有很好的兼容,因此爲了完全解決這個問題只能寫一個組件來解決這個麻煩的問題,這裏爲何是組件而不是指令是由於,是有緣由的,下面會講到。css
Caniuse上顯示sticky的兼容性以下:html
Sticky的做用至關於relative和fixed的結合體,當修飾的目標節點再屏幕中時表現爲relative,當要超出的時候是fixed的形式展示,由於這個特性,咱們就能夠來實現一個sticky的模擬效果。git
<template> <div class="sticky" :style="getPosition"> <div class="sticky-warp"> <slot></slot> </div> </div> </template>
代碼解讀:這裏我使用了組件來實現,而不用指令來實現的緣由是:指令雖然是無侵入性的,更方便使用,但是有一個弊端就是當修飾的節點fixed的時候會脫離文檔流,會改變滾動的條的高度,若是僅僅是配合原生滾動條來實現是沒問題的(固然這也會存在滾動過快的問題),但是因爲是配合自定義滾動因此,採起這種折中的方式來實現。最外層是一個sticky層,判斷瀏覽器是否支持sticky,不支持就使用relative來代替,這樣也就不會改變瀏覽器高度的狀況了,而後動態改變stick-warp層的postion來實現效果。github
<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就能夠完成了。瀏覽器
<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/stickybabel