✨(component): affix组件 新增scroll回调,修改props
This commit is contained in:
parent
4a52df1f28
commit
aea1936da4
@ -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();
|
||||||
});
|
});
|
||||||
|
@ -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> |
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
::: contributor affix
|
::: contributor affix
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user