基本示例
// 在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;