(component): affix组件 新增scroll回调,修改props

This commit is contained in:
0o张不歪o0 2022-06-27 15:30:04 +08:00
parent 4a52df1f28
commit aea1936da4
2 changed files with 58 additions and 51 deletions

View File

@ -12,27 +12,29 @@ export default {
import "./index.less"; import "./index.less";
import { ref, onMounted, onUnmounted, nextTick, computed } from "vue"; import { ref, onMounted, onUnmounted, nextTick, computed } from "vue";
export interface LayAiffxProps { export interface LayAiffxProps {
top?: number; offset?: number;
bottom?: number;
target?: HTMLElement; target?: HTMLElement;
position?: string;
} }
const props = withDefaults(defineProps<LayAiffxProps>(), { const props = withDefaults(defineProps<LayAiffxProps>(), {
top: 0, offset: 0,
position: 'top',
target: () => { target: () => {
return document.body; return document.body;
}, },
}); });
const emit = defineEmits(['scroll'])
const outWindow = ref(false); const outWindow = ref(false);
const affixTop = ref(false);
const dom = ref(); const dom = ref();
let changeScrollTop = 0; let changeScrollTop = 0;
let orginOffsetLeft = 0; let orginOffsetLeft = 0;
let orginOffsetTop = 0;
let marginLeft = 0; let marginLeft = 0;
let marginTop = 0; let marginTop = 0;
let fixedTop = 0; let marginBottom = 0;
let fixedBottom = 0; let fixedOffset = 0;
const getStyle = computed(() => { const getStyle = computed(() => {
if (outWindow.value && dom.value) { if (outWindow.value && dom.value) {
let style = { let style = {
@ -41,17 +43,12 @@ const getStyle = computed(() => {
bottom: "unset", bottom: "unset",
left: orginOffsetLeft - marginLeft + "px", left: orginOffsetLeft - marginLeft + "px",
}; };
if (affixTop.value) { if (props.position === 'top') {
style.top = fixedTop - marginTop + "px"; style.top = fixedOffset - marginTop + "px";
return style;
} else { } else {
if (props.hasOwnProperty("bottom")) { style.bottom = fixedOffset - marginBottom + "px";
style.bottom = props.bottom + "px"; }
return style; return style;
} else {
return {};
}
}
} }
}); });
// //
@ -59,11 +56,10 @@ const checkInWindow = () => {
if (dom.value) { if (dom.value) {
let offsetTop = dom.value.offsetTop; let offsetTop = dom.value.offsetTop;
let scrollTop = props.target?.scrollTop; let scrollTop = props.target?.scrollTop;
if (props.position === 'top') {
if (typeof props.bottom === "undefined") {
//top -+offsetTop //top -+offsetTop
let result = offsetTop - scrollTop + props.target.offsetTop; let result = offsetTop - scrollTop + props.target.offsetTop;
if (result < fixedTop) { if (result < fixedOffset) {
if (outWindow.value) { if (outWindow.value) {
if (scrollTop <= changeScrollTop) { if (scrollTop <= changeScrollTop) {
outWindow.value = false; outWindow.value = false;
@ -71,9 +67,7 @@ const checkInWindow = () => {
} else { } else {
changeScrollTop = scrollTop; changeScrollTop = scrollTop;
outWindow.value = true; outWindow.value = true;
affixTop.value = true;
} }
return;
} }
} else { } else {
//bottom + - - //bottom + - -
@ -84,20 +78,20 @@ const checkInWindow = () => {
let result = viewHeight + scrollTop - offsetTop - dom.value.offsetHeight; let result = viewHeight + scrollTop - offsetTop - dom.value.offsetHeight;
if (outWindow.value) { if (outWindow.value) {
if (scrollTop >= changeScrollTop) { if (scrollTop >= changeScrollTop) {
if (props.bottom == 0) {
console.log(scrollTop);
}
outWindow.value = false; outWindow.value = false;
} }
} else { } else {
if (result < fixedBottom) { if (result < fixedOffset) {
changeScrollTop = scrollTop - result + props.bottom; changeScrollTop = scrollTop - result + props.offset
console.log(changeScrollTop);
outWindow.value = true; outWindow.value = true;
affixTop.value = false;
} }
} }
} }
emit('scroll', {
targetScroll: scrollTop,
affixed: outWindow.value,
offset: !outWindow.value ? 0 : Math.abs(scrollTop - changeScrollTop)
});
} }
}; };
@ -112,14 +106,15 @@ const getDomStyle = (dom: any, attr: string) => {
onMounted(() => { onMounted(() => {
nextTick(() => { nextTick(() => {
orginOffsetLeft = dom.value.getBoundingClientRect().left; orginOffsetTop = dom.value.offsetTop - props.target.offsetTop
fixedTop = props.top + props.target.offsetTop; orginOffsetLeft = dom.value.getBoundingClientRect().left
if (typeof props.bottom !== "undefined") { marginLeft = parseFloat(getDomStyle(dom.value, 'marginLeft'))
fixedBottom = marginTop = parseFloat(getDomStyle(dom.value, 'marginTop'))
props.bottom + parseFloat(getDomStyle(dom.value, "marginBottom")); marginBottom = parseFloat(getDomStyle(dom.value, 'marginBottom'))
fixedOffset = props.offset + props.target.offsetTop
if (props.position === 'bottom') {
fixedOffset = props.offset
} }
marginLeft = parseFloat(getDomStyle(dom.value, "marginLeft"));
marginTop = parseFloat(getDomStyle(dom.value, "marginTop"));
props.target.addEventListener("scroll", checkInWindow, true); props.target.addEventListener("scroll", checkInWindow, true);
checkInWindow(); checkInWindow();
}); });

View File

@ -10,22 +10,22 @@
::: title 基础使用 ::: title 基础使用
::: :::
::: demo 使用 `lay-affix` 标签, 创建锚点,`target` 属性用于需要监听其滚动事件的元素,默认为 `document.body` ,`top`设置距离容器顶部偏移量 ::: demo 使用 `lay-affix` 标签, 创建锚点,`target` 属性用于需要监听其滚动事件的元素,默认为 `document.body` ,`offset`设置距离容器的偏移量
<template> <template>
<div style="width:100%;height:200px"> <div style="width:100%;height:200px">
<lay-affix :target="target" :top="0" v-if="target"> <lay-affix :target="target" v-if="target">
<lay-button type="normal">固定在最顶部</lay-button> <lay-button type="normal">固定在最顶部</lay-button>
</lay-affix> </lay-affix>
<lay-affix :target="target" :top="38" v-if="target" style="margin-left:150px;"> <lay-affix :target="target" :offset="38" v-if="target" style="margin-left:150px;">
<lay-button type="normal">固定在距离顶部38px</lay-button> <lay-button type="normal">固定在距离顶部38px</lay-button>
</lay-affix> </lay-affix>
<lay-affix :target="target" :top="76" v-if="target" style="margin-left:350px"> <lay-affix :target="target" :offset="76" v-if="target" style="margin-left:350px">
<lay-button type="normal">固定在距离顶部76px</lay-button> <lay-button type="normal">固定在距离顶部76px</lay-button>
</lay-affix> </lay-affix>
<lay-affix :target="target" :top="114" v-if="target" style="margin-left:550px"> <lay-affix :target="target" :offset="114" v-if="target" style="margin-left:550px">
<lay-button type="normal">固定在距离顶部114px</lay-button> <lay-button type="normal">固定在距离顶部114px</lay-button>
</lay-affix> </lay-affix>
<lay-affix :target="target" :top="152" v-if="target" style="margin-left:750px"> <lay-affix :target="target" :offset="152" v-if="target" style="margin-left:750px">
<lay-button type="normal">固定在距离顶部152px</lay-button> <lay-button type="normal">固定在距离顶部152px</lay-button>
</lay-affix> </lay-affix>
</div> </div>
@ -37,16 +37,20 @@
nextTick(()=>{ nextTick(()=>{
target.value=document.querySelector(".layui-body"); target.value=document.querySelector(".layui-body");
}) })
const color=ref(0)
const scroll=(e)=>{
color.value=e.offset*2
}
</script> </script>
::: :::
::: title 固定在最底部 ::: title 固定在最底部
::: :::
::: demo 使用 `bottom` 属性, 设置距离容器底部偏移量 ::: demo 使用 `position` 属性, 改变定位属性,默认为 `top`,可选值 `bottom`
<template> <template>
<div style="width:100%;height:100px"> <div style="width:100%;height:100px">
<lay-affix :target="target" :bottom="0" v-if="target"> <lay-affix :target="target" :offset="0" position="bottom" v-if="target">
<lay-button type="normal">固定在最底部</lay-button> <lay-button type="normal">固定在最底部</lay-button>
</lay-affix> </lay-affix>
</div> </div>
@ -61,22 +65,30 @@
</script> </script>
::: :::
::: title Aiffx 属性 ::: title Aiffx 属性
::: :::
::: table ::: table
| 属性 | 描述 | 可选值 | | 属性 | 描述 | 可选值 |
| ------ | ---- | -------------- | | ------ | --------------------- | --------------------------------------- |
| top | 顶部偏移量 : number | 0 | | position | 定位属性 : string | `top` `bottom` |
| bottom | 底部偏移量 : number优先级大于`top` | - | | offset | 偏移量 : number,默认为0 | - |
| target | 指定参考容器 : HTMLElement | 默认`document.body`,请务必确保能够正确获取到dom| | target | 指定参考容器 : HTMLElement | 默认`document.body`,请务必确保能够正确获取到dom|
::: :::
::: title Aiffx 事件
:::
::: table
| 属性 | 描述 | 回调参数 |
| ------ | --------------------- | --------------------------------------- |
| scroll | 初始化完成与滚动时触发的回调回调会返回一个object<br><br>`{targetScroll:string,affixed:boolean,offset:number}` |<br/>`targetScroll` 容器滚动距离<br/><br/>`affixed` 是否处于fixed状态<br/><br/>`offset` 与原本位置的距离 <br>&nbsp; |
:::
::: contributor affix ::: contributor affix
::: :::