网上看的几个固钉组件,感觉实现的比较复杂,所以决定简单实现一下,抛砖引玉
源码
<template>
<div class="affix-placeholder" :style="styles">
<slot></slot>
</div>
</template>
<script>
export default {
name: "Affix",
data() {
return {
affixElTop: 0,
scrollTop: 0,
scrollEl: window,
};
},
props: {
offset: { type: Number, default: 0 },
zIndex: { type: [Number, String], default: 100 },
target: {
type: Function,
default: () => window,
},
},
computed: {
styles() {
const result = [];
if (this.scrollTop - this.affixElTop >= this.offset) {
result.push(
{ position: this.isWindow ? "fixed" : "sticky" },
{ zIndex: this.zIndex },
{ top: `${this.offset}px` }
);
}
return result;
},
isWindow() {
return this.scrollEl === window;
},
},
methods: {
handleScroll(e) {
e.stopPropagation();
if (this.isWindow) {
this.scrollTop =
document.documentElement.scrollTop || document.body.scrollTop;
} else {
this.scrollTop = this.scrollEl.scrollTop || 0;
}
},
},
mounted() {
this.scrollEl = this.target();
this.affixElTop = this.$el.getBoundingClientRect().top;
this.scrollEl.addEventListener("scroll", this.handleScroll);
},
beforeDestroy() {
this.scrollEl.removeEventListener("scroll", this.handleScroll);
},
};
</script>
<style>
.affix-placeholder {
min-height: 1px;
}
</style>
文档
Props
| Name | Description | Type | Required | Default |
|---|
| offset | 固定时和滚动容器顶部的距离 | Number | false | 0 |
| zIndex | 固钉状态时的Z轴索引值 | Number / String | false | 100 |
| target | 目标滚动对象,默认为window | Function | false | () => window |
Slots
| Name | Description | Default Slot Content |
|---|
| default | - | - |
示例
<template>
<div>
<div style="height:100px;width:100%">header</div>
<affix style="background:#199;width:100%;height:50px;">我是固钉</affix>
<p v-for="i in 300" :key="i">{{i}}</p>
</div>
</template>
<script>
import Affix from "./affix";
export default {
components: {
Affix,
}
};
</script>