background

Recently, several projects often use SVG pictures, often there are many steps, every time I have to go online to check how to configure, it is better to go through, in-depth understanding, and record.

The configuration steps

To configure the SVG icon in VUE-CLI, follow the steps below.

  1. Need to use Sprite image loader, parse SVG.
npm install svg-sprite-loader --save-dev
Copy the code
  1. Configure vue.config.js and join the parsing of sprite-loader.
module.exports = {
  chainWebpack: config= > {
    // The original SVG rule overwrites all SVG ICONS, so you need to exclude your own SVG first to apply the new Sprite rule
    // SRC /assets/ ICONS is the directory where we will store SVG
    config.module
      .rule('svg')
      .exclude.add(path.join(__dirname, 'src/assets/icons')) // Exclude custom SVG directories
      .end()
    config.module
      .rule('icons') / / the new rules
      .test(/\.svg$/)
      .include.add(path.join(__dirname, 'src/assets/icons')) // The new rule applies to the directory where we store SVG
      .end()
      .use('svg-sprite-loader') // Use sprite-loader to unload
      .loader('svg-sprite-loader')
      .options({
        symbolId: 'icon-[name]'
      })
      .end()
  }
}
Copy the code

  1. Create a global SvgIcon component that displays an SVG icon on a page. Component location:src/components/SvgIcon.vue
<template>
    <svg class="svg-icon" aria-hidden="true">
        <use :xlink:href="`#icon-${name}`" />
    </svg>
</template>

<script>
export default {
  name: 'SvgIcon'.props: {
    name: { // SVG file name
      type: String.required: true}}}</script>

<style scoped>
.svg-icon {
  width: 1em;
  height: 1em;
  vertical-align: -0.15 em;
  fill: currentColor;
  overflow: hidden;
}
</style>

Copy the code
  1. In main.js, the SvgIcon component is introduced globally and all SVG ICONS are loaded.
import Vue from 'vue'
import SvgIcon from '@/components/SvgIcon'/ / SVG components

// 1. Register SvgIcon globally
Vue.component('svg-icon', SvgIcon)
// 2. Load all SVG ICONS
const requireContext = require.context('./assets/icons'.false./\.svg$/)
requireContext.keys().forEach(requireContext)
Copy the code
  1. The SVG in thesrc/asset/iconsdirectory

  1. Reference it on the page, and you’re done.
<svg-icon name="book" /> <! -- name is the name of the SVG icon file.
Copy the code

Afterword.

Read a lot of articles about the configuration of SVG, often take doctrine, direct use, some unreasonable place also spread ten, ten spread hundred.

1. Introduce SVG icon

Here’s the original:

const req = require.context('./svg'.false./\.svg$/)
const requireAll = requireContext= > requireContext.keys().map(requireContext)
requireAll(req)
Copy the code

RequireContext => requireContext.keys().map(requireContext) requireContext => requireContext.keys().map(requireContext) And the end goal is just to require the resource in, and there is no point in using map, so I changed it to:

const requireContext = require.context('./assets/icons'.false./\.svg$/)
requireContext.keys().forEach(requireContext)
Copy the code

About requreiContext

A) require.context() is used to load multiple resources. RequreiContext is the result of require.context(), which is a function. The printed code looks like this:

function webpackContext(req) {
  var id = webpackContextResolve(req);
  return __webpack_require__(id);
}
Copy the code

This function loads a resource by name and returns a resource object such as {default:{… }} instead!

B) requreiContext prototype has three attributes, ID, keys, and resolve, which are functions. Keys returns a list of file names for all resources, and resolve returns the full path to the resource’s relative project. Print the prototype requreicontext. prototype and get the following result:

Printing requireContext.keys() yields the following result:

2. SvgIcon components

Most articles on the web use this version:

<template>
  <svg :class="svgClass" aria-hidden="true">
    <use :xlink:href="iconName" />
  </svg>
</template>

<script>
export default {
  name: 'SvgIcon'.props: {
    iconClass: {
      type: String.required: true
    },
    className: {
      type: String.default: ' '}},computed: {
    iconName() {
      return `#icon-The ${this.iconClass}`
    },
    svgClass() {
      if (this.className) {
        return 'svg-icon ' + this.className
      } else {
        return 'svg-icon'}}}}</script>

<style scoped>
.svg-icon {
  width: 1em;
  height: 1em;
  vertical-align: -0.15 em;
  fill: currentColor;
  overflow: hidden;
}
</style>
Copy the code

Svgicon (svGIcon, svGIcon, svGIcon, svGIcon, svGIcon) Something like this will do:

<svg-icon name="book" class="myicon" />
Copy the code

B) iconClass is not easy to understand. There is no need to evaluate the iconName property because the component is defined and the name property is not changed.

After modification, it becomes the compact version:

<template>
    <svg class="svg-icon" aria-hidden="true">
        <use :xlink:href="`#icon-${name}`" />
    </svg>
</template>

<script>
export default {
  name: 'SvgIcon'.props: {
    name: {
      type: String.required: true}}}</script>

<style scoped>
.svg-icon {
  width: 1em;
  height: 1em;
  vertical-align: -0.15 em;
  fill: currentColor;
  overflow: hidden;
}
</style>
Copy the code

Sure, there may be performance or other considerations, but I don’t see the need to add those at the moment.

3. Obtain the SVG icon

I often go to the website is this, Alibaba vector icon library, resources are very rich.