vue3 自定义指令并实现页面元素平滑上升

基本示例

// 在directives/example.ts中
import type { Directive } from "vue";
/**
 * 示例
 */
const example: Directive = {
  mounted(el) {
    console.log("mounted", el);
  },
  beforeUnmount(el) {
    console.log("beforeUnmount", el);
  }
};
export default example;

封装全局指令

// 在directives/index.ts中
import type { App, Directive } from "vue";
import example from "./example"; // 示例
const list: {
  [key: string]: Directive;
} = {
  example
};
const setDirectives = {
  install(app: App<Element>) {
    Object.keys(list).forEach((key) => {
      app.directive(key, list[key]);
    });
  }
};
export default setDirectives;

挂载

// 在main.ts中
import useDirective from "@/directives/index.ts"; // 自定义指令
const app = createApp(App);
app.use(useDirective);

使用

<div v-example></div>

元素平滑上升

import type { Directive } from "vue";
/**
 * 平滑滚动
 */
const DISTANCE = 100;
const DURATION = 500;
const map = new WeakMap();
// 判断元素是否与视口区域重叠
const ob = new IntersectionObserver((entries) => {
  for (const entrie of entries) {
    // 出现在了视口
    if (entrie.isIntersecting) {
      const animation = map.get(entrie.target);
      animation && animation.play(); // 启动动画
      ob.unobserve(entrie.target); // 执行过之后就关闭监听
    }
  }
});
// 判断元素是否在视口区域
const isBelowViewport = (el: Element) => {
  const rect = el.getBoundingClientRect();
  return rect.top - window.innerHeight > 0;
};
const smoothScrolling: Directive = {
  mounted(el: Element) {
    // 已经在视口区域就不做处理
    if (!isBelowViewport(el)) return;
    // 动画配置
    const animation = el.animate(
      [
        {
          transform: `translateY(${DISTANCE}px)`,
          opacity: "0.5"
        },
        {
          transform: `translateY(0)`,
          opacity: "1"
        }
      ],
      {
        duration: DURATION,
        easing: "ease-out",
        fill: "forwards"
      }
    );
    animation.pause(); // 暂停动画
    map.set(el, animation);
    ob.observe(el); // 监听元素是否进入视口
  },
  unmounted(el: Element) {
    ob.unobserve(el); // 关闭监听
  }
};
export default smoothScrolling;
posted @ 2025-09-15 11:43  小周同学~  阅读(13)  评论(0)    收藏  举报