很多網站都會使用到頁面往下滑動時header吸附至頂端的功能這次就寫個vue自定義指令來完成這個功能!
知識點
- 動態加入style sheet
- 獲取滾動條上放位置兼容寫法
offsetHeight
#js
export default {
install (Vue) {
// 優化
function debounce (cb, delay) {
let timer = null
return function () {
clearTimeout(timer)
timer = setTimeout(cb, delay)
}
}
// 自動添加css檔案
function loadCssCode (code) {
// 防止我方公司preRender造成的重複添加問題
if (window.__PRERENDER_PROCESSING) return
const style = document.createElement('style')
style.type = 'text/css'
style.rel = 'stylesheet'
try {
style.appendChild(document.createTextNode(code))
} catch (ex) {
style.styleSheet.cssText = code
}
const head = document.getElementsByTagName('head')[0]
head.appendChild(style)
}
// 核心邏輯(頁面Y大於麼幫元素自身高度兩倍距離的時候加上fixed樣式與動效反之則移除)
function fixHandler (el, fixPosY) {
// 兼容寫法獲取滾輪上方位置數值
const screenTop = Math.max(
window.pageYOffset,
document.documentElement.scrollTop,
document.body.scrollTop
)
const headerHeight = el.offsetHeight
if (el.classList.contains('fixe-top-header--active') && screenTop >= fixPosY + headerHeight * 2) return
if (screenTop > fixPosY + headerHeight * 2) {
el.classList.add('fixe-top-header--active')
el.classList.add('fixe-top-header--fadeIn')
el.classList.remove('fixe-top-header--fadeOut')
} else {
el.classList.remove('fixe-top-header--active')
el.classList.remove('fixe-top-header--fadeIn')
el.classList.add('fixe-top-header--fadeOut')
}
}
Vue.directive('fixe-top', {
inserted (el, binding) {
// 參數css名稱(必傳),動效名稱,
const { cssName, animationNameIn, animationNameOut, duration, zIndex } = binding.value
// 初始化樣式與動效
loadCssCode(`
.${cssName}--active{
position:fixed;
left:0;
top:0;
right:0;
z-index:${zIndex || 999}
}
.${cssName}--fadeIn{
animation: ${animationNameIn || ' fixe-fade-in'} ${(duration || 1000) / 1000}s;
}
.${cssName}--fadeOut{
animation: ${animationNameOut || ' fixe-fade-Out'} ${(duration || 1000) / 1000}s;
}
@keyframes fixe-fade-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes fixe-fade-Out {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
`)
// 目標元素
const fixPosY = el.offsetTop
window.addEventListener(
'scroll',
debounce(() => fixHandler(el, fixPosY), 10)
)
}
})
}
}
#註冊
import ScrollFixTop from '@/plugins/scrollFixTop'
Vue.use(ScrollFixTop)
#使用
v-fixe-top="{
cssName:'fixe-top-header' //定位的目標className,
animationNameIn:'', //fix時的動畫
animationNameOut:'', //fix拔掉時的動畫
duration:1000,
zIndex:30 //目標fix後的層級
}"
參考: