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;
本文来自博客园,作者:小周同学~,转载请注明原文链接:https://www.cnblogs.com/xiaozhou-wuyu/p/19092605

浙公网安备 33010602011771号