跳至主要內容

自定义插件开发与配置

前端攻城喵...Vuepress插件 APIHooks大约 2 分钟

自定义插件开发与配置

通过 Hooks 方式实现浏览器标签页的动态标题切换组件

import { onMounted, watch } from "vue";
import { defineClientConfig } from "@vuepress/client";
import { useRoute } from "vue-router";

const useDynamicTitle = () => {
  let recoverTimeout;
  let originTitle;

  const config = {
    showIcon: SHOW_ICON,
    showText: SHOW_TEXT,
    hideIcon: HIDE_ICON,
    hideText: HIDE_TEXT,
    recoverTime: RECOVER_TIME,
  };

  const getIconElm = () => {
    let elm = document.querySelector("link[rel=icon]");
    if (elm === null) {
      elm = document.createElement("link");
      elm.setAttribute("rel", "icon");
      document.head.appendChild(elm);
    }
    return elm;
  };

  const hidden = () => {
    if (config.hideIcon !== "") {
      getIconElm().setAttribute("href", config.hideIcon);
    }
    document.title = config.hideText;
    clearTimeout(recoverTimeout);
  };

  const visible = () => {
    if (config.showIcon !== "") {
      getIconElm().setAttribute("href", config.showIcon);
    }
    document.title = config.showText + " " + originTitle;
    recoverTimeout = setTimeout(() => {
      document.title = originTitle;
    }, config.recoverTime);
  };

  onMounted(() => {
    originTitle = document.title;
    console.log(originTitle, document.title);

    if (config.showIcon !== "") {
      getIconElm().setAttribute("href", config.showIcon);
    }
    document.addEventListener("visibilitychange", () => {
      document.hidden ? hidden() : visible();
    });
  });

  const route = useRoute();
  watch(
    () => route.path,
    (to, from) => {
      if (to !== from) {
        // INFO: 延迟执行是因为路由变化时获取到的title不是最新的
        setTimeout(() => {
          originTitle = document.title;
          clearTimeout(recoverTimeout);
        }, 100);
      }
    }
  );
};

export default defineClientConfig({
  setup() {
    useDynamicTitle();
  },
});
  • dynamic-title 目录下新建 index.js,键入如下代码
import { getDirname, path } from "@vuepress/utils";

const __dirname = getDirname(import.meta.url);

const plugin = (options = {}) => ({
  name: "@vuepress/plugin-dynamic-title",
  clientConfigFile: path.resolve(__dirname, "./dynamicTitlePlugin.js"),
  define() {
    const {
      showIcon = "",
      showText = "(/≧▽≦/)咦!又好了!",
      hideIcon = "",
      hideText = "(●—●)喔哟,崩溃啦!",
      recoverTime = 3000,
    } = options;

    return {
      SHOW_ICON: showIcon,
      SHOW_TEXT: showText,
      HIDE_ICON: hideIcon,
      HIDE_TEXT: hideText,
      RECOVER_TIME: recoverTime,
    };
  },
});

export default plugin;
  • 修改 .vuepress 目录下的 config.ts 文件
import { defineUserConfig } from "vuepress";
import dynamicTitle from "../plugins/dynamic-title/index.js";

export default defineUserConfig({
  ...

  plugins: [
    ...

    dynamicTitle({
      showText: "✧*。 (ˊᗜˋ*) ✧*",
      hideText: "◝(⑅•ᴗ•⑅)◜",
      recoverTime: 5000,
    }),
  ],
});
  • 刷新浏览器后,进行切换标签页时就可以看到效果了

通过 Vue 组件方式实现网页背景效果

  • 安装 canvas-next.js 依赖
npm install --save canvas-nest.js
  • plugins 目录下创建 plugins/canvas-nest 目录
  • canvas-nest 目录新建 CanvasNest.vue,键入如下代码
<template>
  <!-- see https://v2.vuepress.vuejs.org/zh/advanced/cookbook/usage-of-client-config.html -->
  <ClientOnly></ClientOnly>
</template>

<script setup>
// 在这里导入 CanvasNest,那构建时会报 `window is not defined` 异常
// import CanvasNest from "canvas-nest.js";
import { onMounted, onUnmounted } from "vue";

const config = {
  opacity: 0.8,
  count: 120,
  zIndex: 10,
};

let cn;

onMounted(() => {
  // see https://v2.vuepress.vuejs.org/zh/guide/#%E5%AE%83%E6%98%AF%E5%A6%82%E4%BD%95%E5%B7%A5%E4%BD%9C%E7%9A%84
  // INFO: 打包构建时会创建 SSR 版本,导致在 Node 环境下报 `window is not defined`,通过 `import then` 方式确保 `canvas-next.js` 加载完成后再渲染
  import("canvas-nest.js").then((module) => {
    const CanvasNest = module.default;
    cn = new CanvasNest(document.body, config);
  });
});

onUnmounted(() => {
  cn && cn.destroy();
});
</script>

...

  • canvas-nest 目录下新建 canvasNestPlugin.js,键入如下代码
import { defineClientConfig } from "@vuepress/client";
import CanvasNest from "./CanvasNest.vue";

export default defineClientConfig({
  rootComponents: [CanvasNest],
});
  • canvas-nest 目录下新建 index.js,键入如下代码
import { getDirname, path } from "@vuepress/utils";

const __dirname = getDirname(import.meta.url);

const plugin = (options = {}) => ({
  name: "@vuepress/plugin-canvas-nest",
  clientConfigFile: path.resolve(__dirname, "./canvasNestPlugin.js"),
});

export default plugin;
评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v2.15.8