Vue3封装通用svg组件

我觉得拿自己以前发过的文章应该是不能叫做抄吧!

我之前在iconfont图标库找到了一些比较精美的图标,但是当我兴高采烈的拿着从阿里妈妈图标库去用的时候发现,颜色是黑的,emmmm…,当然颜色是可以修改的,但是有些图标改完后就不是原来的图标了,她已经不是原来的那个她了,哈哈哈哈,接下里,带你从0来封装一个可服用的svg组件。虽然好用但是也不要用太多,可能会导致页面卡顿。

下面正片开始:
首先你需要安装一个插件

npm i svg-sprite-loader -D

然后在vue-config,js当中配置如下:

const { defineConfig } = require("@vue/cli-service");
const path = require("path");
function resolve(dir) {
  return path.join(__dirname, dir);
}
module.exports = defineConfig({
  transpileDependencies: true,
  lintOnSave: false,
  chainWebpack: (config) => {
    config.module.rules.delete("svg"); // 重点:删除默认配置中处理svg
    config.module
      .rule("svg-sprite-loader") // rule 匹配规则
      .test(/\.svg$/) // 用正则匹配 文件
      .include // 包含
      .add(resolve("src/icon")) // 处理svg目录
      .end()
      .use("svg-sprite-loader") // 配置loader  use() 使用哪个loader
      .loader("svg-sprite-loader") // 加载loader
      .options({
        // [name] 变量。一般表示匹配到的文件名 xxx.svg
        // 注意: symbolId  在  
        symbolId: "dl-icon-[name]", // 将所有的.svg 集成到 symbol中,当使用 类名 icon-文件名
      });
  },
});

接下来在src当中创建新文件夹icons,然后在该文件夹下创建index.js,内容如下:

// 这里是 ./svg是路径
const webpackContext = require.context("./svg", false, /\.svg$/);
const requireAll = (requireContext) => {
  // requireContext.keys()   匹配的 文件路径数组
  return requireContext.keys().map(requireContext);
};
// 得到一个完整解析的module数组
requireAll(webpackContext);

接着在icons下创建文件夹svg,与上面相对应。如果你与我配置的路径不对也是需要修改vue.config.js当中的配置的。在svg文件夹下是你想要使用的 XXX.svg,名字根据自己爱好命名即可。
目录结构如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZMycUZPq-1665467594713)(https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/5128f4ab48424d3d805de9c9de5431da~tplv-k3u1fbpfcp-watermark.image?)]

接下来就是封装svg组件了,在components目录下创建ScgIcon.vue文件,文件代码如下:

<template>
  <svg
    :class="svgClass"
    aria-hidden="true"
    :style="
      props.width
        ? `width:${props.width}px;height:${props.width}px;${
            props.cursor ? 'cursor:pointer;' : ''
          }`
        : ''
    "
  >
    <use :xlink:href="iconName" />
  svg>
template>

<script>
import { computed } from "@vue/reactivity";

export default {
  props: {
    iconClass: {
      type: String,
      required: true,
    },
    className: {
      type: String,
      default: "",
    },
    width: {
      type: Number,
      default: 0,
    },
    cursor: {
      type: Boolean,
      default: true,
    },
  },
  setup(props) {
    // 图标在 iconfont 中的名字
    const iconName = computed(() => {
      return `#dl-icon-${props.iconClass}`;
    });
    // 给图标添加上类名
    const svgClass = computed(() => {
      if (props.className) {
        return `svg-icon ${props.className}`;
      }
      return "svg-icon";
    });
    return {
      svgClass,
      iconName,
      props,
    };
  },
};
script>

<style lang="less" scoped>
.svg-icon {
  width: 30px;
  height: 30px;
  vertical-align: -0.15em;
  fill: currentColor;
  overflow: hidden;
  transition: all 1s;
}
.big-svg-icon {
  width: 50px;
  height: 50px;
}
style>

这里我对组件封装并且传入了一些参数,当然你也可以在此基础上对我封装的代码进行修改,参数名词解释如下:

iconClass: 这个就是 XXX.svg的 XXX内容


className: 这个是一个类名根据你传入的类名去使用下面style标签当中的样式,因为我觉得这个并不是很好用,所以对此进行了一些修改


width: 这个就是对传进来的width进行一个动态赋值,因为如果使用类名显得过于臃肿30px,40px,50px等等会需要写很多的类名,并不能按照我的要求随心所欲的去改变大小所以进行了这样的修改


cursor: 鼠标移动是否显示小手,通过true和false来控制,true就是cursor:pointer; false并不会显示小手

不要着急马上就结束了,接下来就是在Vue当中全局注册这个组件,全局使用肯定是要香一点。然后就是在main.js当中去全局注册这个组件。代码如下:

import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";
import "@/icons/index"; // 将src/icons/index.js引入
import SvgIcon from "./components/SvgIcon.vue"; // 引入SvgIcon.vue
// 在这里注册.component("svg-icon", SvgIcon)注意不要放在mount后面,要放在前面
createApp(App).use(router).component("svg-icon", SvgIcon).mount("#app");

接下来你就可以尽情的使用这个组件了。

<template>
  <div
    class="route"
    v-for="item in content"
    :key="item.id"
    @click="toBlog(item)"
  >
    <svg-icon :iconClass="item.iconClass" :width="item.width">svg-icon>
    <div v-if="item.title">{{ item.title }}div>
  div>
template>
<script setup>
const content = [
        { id: 1, iconClass: "home", width: "30", path: "/" },
        { id: 2, iconClass: "wenzhang", width: "30", path: "/blog" },
        { id: 3, iconClass: "ziliao", width: "30" },
]
script>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-We00HV8g-1665467594714)(https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b5bb127f65884d94aa99219d1f50dc29~tplv-k3u1fbpfcp-watermark.image?)]

你可能感兴趣的:(Vue3,vue.js,javascript,前端)