参考链接:https://www.yii666.com/blog/45780.html
添加图标的两种方式:
1. 直接使用element-plus/icons-vue(图标名称网址:https://element-plus.gitee.io/en-US/component/icon.html#icon-collection)
2. 使用svg-sprite-loader自己下载svg图标(SVG图标下载网址:https://www.iconfinder.com/search/icons?family=ionicons-sharp)
先讲方式一:
首先在main.js中导入
import Vue, { createApp } from 'vue' import ElementPlus from 'element-plus' import 'element-plus/dist/index.css' import App from './App.vue' import './assets/css/global.css' import axios from 'axios' // 统一导入el-icon图标 import * as ElIconModules from '@element-plus/icons-vue' import router from "./router/index" // svg图标 import SvgIcon from '@/components/SvgIcon' const app = createApp(App) app.config.productionTip = false app.config.globalProperties.$axios = axios for (let iconName in ElIconModules) { app.component(iconName, ElIconModules[iconName]) } app.use(router) app.use(ElementPlus) app.component('svg-icon', SvgIcon) const req = require.context('./icons/svg', false, /\.svg$/) const requireAll = requireContext => requireContext.keys().map(requireContext) requireAll(req) app.mount('#app')View Code
其实我们在写登录页面时在用户名密码那里用过,来看LoginPage.vue
/* eslint-disable */ <template> <div class="login_container"> <div class="login_box"> <div class="wai"> <!-- 头像区域 --> <div class="avatar_box"> <img src="../assets/head.png" alt="" /> </div> <!-- 登录表单区域 --> <el-form ref="loginFormRef" :model="loginForm" :rules="loginFormRules" label-width="0px" class="login_form" > <!-- 用户名--> <el-form-item prop="username"> <label class="form-label">用户名</label> <el-input v-model="loginForm.username" prefix-icon="User" ></el-input> </el-form-item> <!-- 密码--> <el-form-item prop="password"> <label class="form-label">密码</label> <el-input v-model="loginForm.password" prefix-icon="Key" type="password" ></el-input> </el-form-item> <!-- 按钮区域--> <el-form-item class="btns"> <el-button type="primary" @click="Login">登录</el-button> <el-button type="info" @click="resetLoginForm">重置</el-button> </el-form-item> <div style="display:flex; justify-content:flex-start">{{loginForm.message}}</div> </el-form> </div> </div> </div> </template> <style lang="less" scoped> .login_container { background-color: darkcyan; height: 100%; } .login_box { width: 350px; height: 300px; background-color: white; border-radius: 15px; /*容器内居中*/ position: absolute; left: 40%; top: 50%; transform: translate(-50%, -50%); .avatar_box { height: 130px; width: 130px; border: 1px solid #eee; border-radius: 50%; padding: 10px; /*边框阴影*/ box-shadow: 0 0 10px #ddd; position: absolute; left: 50%; transform: translate(-50%, -50%); background-color: #fff; img { width: 100%; height: 100%; border-radius: 50%; background-color: #993d3d; } } .login_form { position: absolute; bottom: 0; width: 100%; padding: 0 20px; box-sizing: border-box; } .btns { display: flex; justify-content: flex-end; } .wai { background-image: url("../assets/back.jpg"); width: 577px; height: 300px; border-radius: 15px; } } </style> <script> import qs from 'qs' export default { name: 'LoginPage', data () { return { // 数据绑定对象 loginForm: { username: 'lili', password: '123', message: '' }, loginFormRules: { // 验证用户 username: [ {required: true, message: '请输入用户名', trigger: 'blur'}, { min: 3, max: 10, message: '长度在3到10个字符', trigger: 'blur' } ], password: [ {required: true, message: '请输入登录密码', trigger: 'blur'}, { min: 3, max: 15, message: '长度在3到15个字符', trigger: 'blur' } ] } } }, methods: { Login () { /* http://localhost:8081/api/login */ this.$axios .post('http://localhost:8081/api/login', qs.stringify(this.loginForm)) .then(successResponse => { console.log(successResponse.data) if (successResponse.data.code !== 200) { this.loginForm.message = successResponse.data.message } else { console.log('登录成功') console.log(successResponse.data.data.user.user_account) this.$router.push({path: '/JumpTest', query: {param: successResponse.data.data.user.user_account}}) } }) .catch(failResponse => { console.log('12345566') console.log(failResponse) }) }, // // 重置登录表单 resetLoginForm () { this.$refs.loginFormRef.resetFields() } } } </script>View Code
用户名密码那里使用的是element-plus带的图标,这个是在input标签中使用,那如果把它使用到导航页面如何使用呢,看一下NavigationTest.vue
<template> <div class="layout"> <el-container class="container"> <el-aside class="aside"> <div class="head"> <div> <span>后台管理系统</span> </div> </div> <div class="line" /> <el-menu background-color="#222832" text-color="#fff" :router="true" :default-openeds="state.defaultOpen" :default-active='state.currentPath' > <el-menu-item index="/ProFile"> <el-icon><HomeFilled /></el-icon> <span><strong>首页</strong></span> </el-menu-item> <el-sub-menu index="2"> <template #title> <el-icon><Menu /></el-icon> <span><strong>系统管理</strong></span> </template> <el-menu-item-group> <el-menu-item index="2-1"><el-icon><Avatar /></el-icon>角色管理</el-menu-item> <el-menu-item index="/AboutTest"><el-icon><QuestionFilled /></el-icon>关于</el-menu-item> </el-menu-item-group> </el-sub-menu> </el-menu> </el-aside> <el-container class="content"> <HeaderTest /> <div class="main"> <router-view /> </div> <FooterTest /> </el-container> </el-container> </div> </template> <script setup> import { reactive } from 'vue' import { useRouter } from 'vue-router' import HeaderTest from "@/views/HeaderTest.vue" import FooterTest from "@/views/FooterTest.vue" const noMenu = ['/LoginPage'] const router = useRouter() const state = reactive({ showMenu: true, defaultOpen: ['1', '2', '3', '4'], currentPath: '/', }) router.afterEach((to) => { state.showMenu = !noMenu.includes(to.path) }) router.beforeEach((to) => { state.currentPath = to.path document.title = to.name }) </script> <style scoped> .layout { min-height: 100vh; background-color: #ffffff; } .container { height: 100vh; } .aside { width: 200px!important; background-color: #222832; } .head { display: flex; align-items: center; justify-content: center; height: 50px; } .head > div { display: flex; align-items: center; } .head img { width: 50px; height: 50px; margin-right: 10px; } .head span { font-size: 20px; color: #ffffff; } .line { border-top: 1px solid hsla(0,0%,100%,.05); border-bottom: 1px solid rgba(0,0,0,.2); } .content { display: flex; flex-direction: column; max-height: 100vh; overflow: hidden; } .main { height: calc(100vh - 100px); overflow: auto; padding: 10px; } </style> <style> body { padding: 0; margin: 0; box-sizing: border-box; } .el-menu { border-right: none!important; } .el-submenu { border-top: 1px solid hsla(0, 0%, 100%, .05); border-bottom: 1px solid rgba(0, 0, 0, .2); } .el-submenu:first-child { border-top: none; } .el-submenu [class^="el-icon-"] { vertical-align: -1px!important; } a { color: #409eff; text-decoration: none; } .el-pagination { text-align: center; margin-top: 20px; } .el-popper__arrow { display: none; } </style>View Code
没错,就直接使用<el-icon><图标名称 /></el-icon>,图标名称可以去网站上查看
再讲方式二:
首先安装依赖:npm i svg-sprite-loader
接着创建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) { // set svg-sprite-loader config.module .rule('svg') .exclude.add(resolve('src/icons')) .end() config.module .rule('icons') .test(/\.svg$/) .include.add(resolve('src/icons')) .end() .use('svg-sprite-loader') .loader('svg-sprite-loader') .options({ symbolId: 'icon-[name]' }) .end() } })View Code
然后创建文件src/components/SvgIcon/index.vue,src/utils/validation.js
index.vue
<template> <div v-if="isExternal" :style="styleExternalIcon" class="svg-external-icon svg-icon" v-on="$listeners" /> <svg v-else :class="svgClass" aria-hidden="true" v-on="$listeners"> <use :xlink:href="iconName" /> </svg> </template> <script> // doc: https://panjiachen.github.io/vue-element-admin-site/feature/component/svg-icon.html#usage import { isExternal } from '@/utils/validation' export default { name: 'SvgIcon', props: { iconClass: { type: String, required: true }, className: { type: String, default: '' } }, computed: { isExternal() { return isExternal(this.iconClass) }, iconName() { return `#icon-${this.iconClass}` }, svgClass() { if (this.className) { return 'svg-icon ' + this.className } else { return 'svg-icon' } }, styleExternalIcon() { return { mask: `url(${this.iconClass}) no-repeat 50% 50%`, '-webkit-mask': `url(${this.iconClass}) no-repeat 50% 50%` } } } } </script> <style scoped> .svg-icon { width: 1em; height: 1em; vertical-align: -0.15em; fill: currentColor; overflow: hidden; } .svg-external-icon { background-color: currentColor; mask-size: cover!important; display: inline-block; } </style>View Code
validation.js
/** * @param {string} path * @returns {Boolean} */ export function isExternal(path) { return /^(https?:|mailto:|tel:)/.test(path) } /** * @param {string} str * @returns {Boolean} */ export function validUsername(str) { const valid_map = ['admin', 'editor'] return valid_map.indexOf(str.trim()) >= 0 } /** * @param {string} url * @returns {Boolean} */ export function validURL(url) { const reg = /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/ return reg.test(url) } /** * @param {string} str * @returns {Boolean} */ export function validLowerCase(str) { const reg = /^[a-z]+$/ return reg.test(str) } /** * @param {string} str * @returns {Boolean} */ export function validUpperCase(str) { const reg = /^[A-Z]+$/ return reg.test(str) } /** * @param {string} str * @returns {Boolean} */ export function validAlphabets(str) { const reg = /^[A-Za-z]+$/ return reg.test(str) } /** * @param {string} email * @returns {Boolean} */ export function validEmail(email) { const reg = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ return reg.test(email) } /** * @param {string} str * @returns {Boolean} */ export function isString(str) { if (typeof str === 'string' || str instanceof String) { return true } return false } /** * @param {Array} arg * @returns {Boolean} */ export function isArray(arg) { if (typeof Array.isArray === 'undefined') { return Object.prototype.toString.call(arg) === '[object Array]' } return Array.isArray(arg) }View Code
接下来在main.js中引入
import Vue, { createApp } from 'vue' import ElementPlus from 'element-plus' import 'element-plus/dist/index.css' import App from './App.vue' import './assets/css/global.css' import axios from 'axios' // 统一导入el-icon图标 import * as ElIconModules from '@element-plus/icons-vue' import router from "./router/index" // svg图标 import SvgIcon from '@/components/SvgIcon' const app = createApp(App) app.config.productionTip = false app.config.globalProperties.$axios = axios for (let iconName in ElIconModules) { app.component(iconName, ElIconModules[iconName]) } app.use(router) app.use(ElementPlus) app.component('svg-icon', SvgIcon) const req = require.context('./icons/svg', false, /\.svg$/) const requireAll = requireContext => requireContext.keys().map(requireContext) requireAll(req) app.mount('#app')View Code
最后到页面中使用图标,创建一个ProFile.vue
<script> export default { name: 'ProFile', data() { return { activeTab: 'userinfo', englishname: '管理员', password: 'password', phone: '17524320042', email: '[email protected]', privilege: '管理员', user: { oldPassword: '', newPassword: '', confirmPassword: '', }, rules: { oldPassword: [ {required: true, message: '旧密码不能为空', trigger: 'blur'}, { min: 3, max: 15, message: '长度在3到15个字符', trigger: 'blur' } ], newPassword: [ {required: true, message: '新密码不能为空', trigger: 'blur'}, { min: 3, max: 15, message: '长度在3到15个字符', trigger: 'blur' } ], confirmPassword: [ {required: true, message: '确认密码不能为空', trigger: 'blur'}, { min: 3, max: 15, message: '长度在3到15个字符', trigger: 'blur' } ] } } }, methods: { passwordsubmit() { }, emailsubmit() { }, close() { } } } </script> <template> <div class="app-container"> <el-row :gutter="0"> <el-col :span="7" :xs="24"> <el-card class="box-card"> <template v-slot:header> <div class="clearfix"> <span>个人中心</span> </div> </template> <div> <ul class="list-group list-group-striped"> <li class="list-group-item"> <svg-icon icon-class="sharp" /> 姓名 <div class="user-item">{{ englishname }}</div> </li> <li class="list-group-item"> 手机号码 <div class="user-item">{{phone}}</div> </li> <li class="list-group-item"> 邮箱 <div class="user-item">{{email}}</div> </li> <li class="list-group-item"> 所属角色 <div class="user-item">{{ privilege }}</div> </li> </ul> </div> </el-card> </el-col> <el-col :span="15" :xs="24"> <el-card> <template v-slot:header> <div class="clearfix"> <span>基本资料</span> </div> </template> <el-tabs v-model="activeTab"> <el-tab-pane label="基本资料" name="userinfo"> <el-form ref="userRef" :model="user" :rules="rules" label-width="80px"> <el-form-item label="用户昵称" prop="englishname"> <el-input v-model="englishname" maxlength="30" /> </el-form-item> <el-form-item label="邮箱" prop="Email"> <el-input v-model="email" maxlength="30" /> </el-form-item> <el-form-item> <el-button type="primary" @click="emailsubmit">保存</el-button> <el-button type="danger" @click="close">关闭</el-button> </el-form-item> </el-form> </el-tab-pane> <el-tab-pane label="密码修改" name="resetPwd"> <el-form ref="pwdRef" :model="user" :rules="rules" label-width="138px"> <el-form-item label="旧密码" prop="oldPassword"> <el-input v-model="user.oldPassword" placeholder="请输入旧密码" type="password" show-password/> </el-form-item> <el-form-item label="新密码" prop="newPassword"> <el-input v-model="user.newPassword" placeholder="请输入新密码" type="password" show-password /> </el-form-item> <el-form-item label="确认密码" prop="confirmPassword"> <el-input v-model="user.confirmPassword" placeholder="请确认新密码" type="password" show-password/> </el-form-item> <el-form-item> <el-button type="primary" @click="passwordsubmit">保存</el-button> <el-button type="danger" @click="close">关闭</el-button> </el-form-item> </el-form> </el-tab-pane> </el-tabs> </el-card> </el-col> </el-row> </div> </template> <style> .el-col { padding: 10px; } .list-group-item { text-align: left; display: list-item; height: 20px; border-bottom: 1px solid #cccccc; padding: 10px; font-size: 16px; } .user-item { float: right; } .clearfix { font-size: 24px; font-weight: bold; } .el-tabs__item { font-size: 16px !important; } </style>View Code
在姓名那里成功插入图标,sharp图标是从图标网站上下的svg文件,将下载的svg文件放到icons/svg文件夹里面
目录结构如下
标签:Vue,return,const,svg,app,vue,第十五,import,图标 From: https://www.cnblogs.com/smart-zihan/p/17570868.html