加载src下svg图片,不暴露

27 阅读1分钟
<template>
  <component :is="currentComponent" ref="svgRef" :class="props.class" />
</template>

<script setup lang="ts">
  import type { Component } from 'vue';
  import { computed, ref, useAttrs, watch } from 'vue';
  import { uuid } from '@/utils';

  const modules = import.meta.globEager('@/assets/images/webPuc/svgs/*.svg', {
    as: 'component',
  });
  const attrs = useAttrs();

  const props = defineProps({
    name: {
      type: String,
      require: true,
    },
    class: {
      type: String,
      default: 'webPuc_svg',
    },
    useViewBox: {
      type: Boolean,
      default: false,
    },
  });

  const currentComponent = computed<Component>(() => {
    const fileName = `/${props.name}.svg`;
    const currentKey = Object.keys(modules).find((key) => {
      return key.endsWith(fileName);
    });
    try {
      return modules[currentKey] as Component;
    } catch (error) {
      throw new Error(`not found svg file:${fileName}`);
    }
  });

  const svgRef = ref<any>();

  watch(svgRef, (newVal) => {
    if (newVal) {
      Object.entries({ ...attrs, ...props }).forEach(([k, v]) => {
        if (v !== undefined) {
          newVal.$el?.setAttribute(k, String(v));
        }
      });

      try {
        /* 生成的svg代码没有viewBox属性,需要额外添加 */
        if (!attrs.viewBox && !props.useViewBox) {
          newVal.$el?.setAttribute(
            'viewBox',
            `0 0 ${newVal.$el.getAttribute('width')} ${newVal.$el.getAttribute(
              'height'
            )}`
          );
        }

        const flagMap = {};
        if (!newVal?.$el) return;
        newVal.$el.innerHTML = newVal.$el.innerHTML.replace(
          /url\(#\w{1}\)/g,
          (key: string) => {
            const k = key.slice(5, -1);
            flagMap[k] = uuid();
            return `url(#${flagMap[k]})`;
          }
        );
        newVal.$el.innerHTML = newVal.$el.innerHTML.replace(
          /id="\w{1}"/g,
          (key: string) => {
            const k = key.slice(4, -1);
            return `id="${flagMap[k]}"`;
          }
        );
      } catch (error) {
        window.$wsLogs.error('catched an error', error);
      }
    }
  });
</script>

<style scoped lang="less">
  svg {
    width: auto;
    height: auto;
  }
</style>