|
@@ -0,0 +1,71 @@
|
|
|
+import Vue from "vue";
|
|
|
+
|
|
|
+Vue.directive("sticky", {
|
|
|
+ inserted(el, binding) {
|
|
|
+ const referParent = binding.value.referParent
|
|
|
+ ? document.querySelector(binding.value.referParent)
|
|
|
+ : el.parentElement;
|
|
|
+ const stickyTop = binding.value.stickyTop || 0; // 设置吸顶的偏移量,默认0
|
|
|
+
|
|
|
+ const parent = el.parentElement;
|
|
|
+ const placeholder = document.createElement("div"); // 用于防止塌陷的占位元素
|
|
|
+ const elRect = el.getBoundingClientRect();
|
|
|
+ const siblingRect = el.nextElementSibling.getBoundingClientRect();
|
|
|
+ placeholder.style.height = `${siblingRect.top - elRect.top}px`;
|
|
|
+ placeholder.style.visibility = "hidden";
|
|
|
+ placeholder.style.display = "none";
|
|
|
+ parent.insertBefore(placeholder, el);
|
|
|
+
|
|
|
+ const parentRect = referParent.getBoundingClientRect();
|
|
|
+
|
|
|
+ const onScroll = () => {
|
|
|
+ const placeholderRect = placeholder.getBoundingClientRect();
|
|
|
+ const isSticky = placeholderRect.top < parentRect.top + stickyTop;
|
|
|
+ el.style.width = `${el.offsetWidth}px`;
|
|
|
+
|
|
|
+ if (isSticky) {
|
|
|
+ el.style.position = "fixed";
|
|
|
+ el.style.top = `${parentRect.top}px`;
|
|
|
+ el.style.left = `${elRect.left}px`;
|
|
|
+ el.style.boxShadow = `0 2px 2px 1px #eee`;
|
|
|
+ el.style.zIndex = 99;
|
|
|
+ placeholder.style.display = "block";
|
|
|
+ } else {
|
|
|
+ el.style.position = "";
|
|
|
+ el.style.top = "";
|
|
|
+ el.style.left = "";
|
|
|
+ el.style.boxShadow = "";
|
|
|
+ placeholder.style.display = "none";
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ // 监听滚动事件
|
|
|
+ referParent.addEventListener("scroll", onScroll);
|
|
|
+
|
|
|
+ // 监听窗口大小变化,更新元素宽度
|
|
|
+ const onResize = () => {
|
|
|
+ const parentRect = parent.getBoundingClientRect();
|
|
|
+ if (el.style.position === "fixed") {
|
|
|
+ el.style.width = `${parentRect.width}px`;
|
|
|
+ el.style.left = `${parentRect.left}px`;
|
|
|
+ }
|
|
|
+ placeholder.style.width = `${el.offsetWidth}px`;
|
|
|
+ };
|
|
|
+ window.addEventListener("resize", onResize);
|
|
|
+
|
|
|
+ // 移除监听器的清理函数
|
|
|
+ el._stickyCleanup = () => {
|
|
|
+ referParent.removeEventListener("scroll", onScroll);
|
|
|
+ window.removeEventListener("resize", onResize);
|
|
|
+ if (placeholder.parentElement) {
|
|
|
+ placeholder.parentElement.removeChild(placeholder);
|
|
|
+ }
|
|
|
+ };
|
|
|
+ },
|
|
|
+ unbind(el) {
|
|
|
+ // 清理事件监听器和占位元素
|
|
|
+ if (el._stickyCleanup) {
|
|
|
+ el._stickyCleanup();
|
|
|
+ }
|
|
|
+ },
|
|
|
+});
|