构建登录页面
1.创建views/login/index.vue
文件;
views/login/index.vue
<template>
<div class="login-container">
<el-form class="login-form">
<div class="title-container">
<h3 class="title">用户登录</h3>
</div>
<el-form-item>
<span class="svg-container">
<el-icon><Avatar /></el-icon>
</span>
<el-input placeholder="username" name="username" type="text"></el-input>
</el-form-item>
<el-form-item>
<span class="svg-container">
<el-icon><Avatar /></el-icon>
</span>
<el-input placeholder="password" name="password"></el-input>
<span class="show-pwd">
<el-icon><Avatar /></el-icon>
</span>
</el-form-item>
<el-button type="primary" style="width: 100%; margin-bottom: 30px"
>登录</el-button
>
</el-form>
</div>
</template>
<script setup>
import { Avatar } from '@element-plus/icons'
</script>
<style lang="scss" scoped>
$bg: #2d3a4b;
$dark_gray: #889aa4;
$light_gray: #eee;
$cursor: #fff;
.login-container {
min-height: 100%;
width: 100%;
background-color: $bg;
overflow: hidden;
.login-form {
position: relative;
width: 520px;
max-width: 100%;
padding: 160px 35px;
margin: 0 auto;
overflow: hidden;
.title-container {
width: 100%;
padding-bottom: 20px;
text-align: center;
font-weight: bold;
color: #fff;
font-size: 26px;
}
::v-deep .el-form-item {
border: 1px solid rgba(255, 255, 255, 0.1);
background-color: rgba(0, 0, 0, 0.1);
border: 5px;
color: #454545;
}
.svg-container {
display: inline-block;
text-align: center;
}
::v-deep .el-input {
display: inline-block;
width: 85%;
height: 47%;
input {
background: transparent;
border: 0px;
border-radius: 0px;
color: $light_gray;
padding: 12px 5px 12px 15px;
caret-color: $cursor;
}
}
}
.svg-container {
padding: 6px 5px 6px 15px;
color: $dark_gray;
vertical-align: middle;
display: inline-block;
}
.show-pwd {
position: absolute;
right: 10px;
top: 7px;
font-size: 16px;
color: $dark_gray;
cursor: pointer;
user-select: none;
}
}
</style>
2.在route/index.js中增加一下路由配置;
route/index.js
import { createRouter, createWebHashHistory } from 'vue-router'
const publicRoutes = [
{
path: '/login',
component: () => import('@/views/login/index')
}
]
const router = createRouter({
history: createWebHashHistory(),
routes: publicRoutes
})
export default router
3.创建全局的style
style/index.scss
html,
body {
height: 100%;
margin: 0;
padding: 0;
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB,
Microsoft YaHei, Arial, sans-serif;
}
#app {
height: 100%;
}
*,
*:before,
*:after {
box-sizing: inherit;
margin: 0;
padding: 0;
}
a:focus,
a:active {
outline: none;
}
a,
a:focus,
a:hover {
cursor: pointer;
color: inherit;
text-decoration: none;
}
div:focus {
outline: none;
}
.clearfix {
&:after {
visibility: hidden;
display: block;
font-size: 0;
content: ' ';
clear: both;
height: 0;
}
}
main.ts中导入:
main.ts
import '@/styles/index.scss'
Icon图标
之前都是通过路径引入图标:
html
<img src="../assets/icons/user.svg" />
显然是很不方便的,此次封装的目的就是为了简化写法和可复用性;
在我们项目中该所使用的icon图标,一共分为两类:
1.element-plus的图标;
2.自定义的svg图标;
对于element-plus的图标我们可以直接通过el-icon来进行显示,但是自定义图标的话,我们需要自定义组件,来显示自定义的svg图标;
这个组件需要拥有两种能力:
1.显示外部svg图标;
2.现实项目内的svg图标;
创建图标组件
创建utils/validate.js;
utils/validate.js
/**
* 判断是否为外部资源
*/
export function isExternal(path) {
return /^(https?:|mailto:|tel:)/.test(path)
}
创建components/SvgIcon/index.vue;
components/SvgIcon/index.vue
<template>
<!--展示外部图标-->
<div
v-if="isExternal"
:style="styleExternalIcon"
class="svg-external-icon svg-icon"
:class="className"
></div>
<!--展示内部图标-->
<svg v-else class="svg-icon" :class="className" aria-hidden="true">
<use :xlink:href="iconName"></use>
</svg>
</template>
<script setup>
import { defineProps, computed } from 'vue'
import { isExternal as external } from '@/utils/validate'
const props = defineProps({
// icon图标
icon: {
type: String,
required: true
},
// 图标类名
className: {
type: String,
default: ''
}
})
/**
*判断当前图标是否为外部图标
*/
const isExternal = computed(() => external(props.icon))
/**
* 外部图标样式
*/
const styleExternalIcon = computed(() => ({
mask: `url(${props.icon}) no-repeat 50% 50%`,
'-webkit-mask': `url(${props.icon}) no-repeat 50% 50%`
}))
/**
* 内部图标
*/
const iconName = computed(() => `#icon-${props.icon}`)
</script>
<style lang="scss" scoped>
.svg-icon {
/** 将icon大小设置和字体大小一致,后续在通过svg-icon使用icon的时候,可直接设置图标的font-size即可控制图标的大小 */
width: 1em;
height: 1em;
vertical-align: -0.15em;
/** 因icon大小被设置为字体大小一致,而span等标签的下边缘会和字体的基线对齐,顾需设置一个往下的偏移比例,来纠正视觉上的未对齐效果*/
fill: currentColor;
/** 定义元素的颜色,currentColor是一个变量,这个变量就表示当前元素的color,如果当前元素未设置color值,则从父元素继承 */
overflow: hidden;
}
.svg-external-icon {
background: currentColor;
mask-size: cover !important;
display: inline-block;
}
</style>
接着在login页面使用图标组件,这里是一个外部图标的显示:
views/login/index.vue
<span class="svg-container">
<SvgIcon icon="https://res.lgdsunday.club/user.svg"></SvgIcon>
</span>
外部图标成功显示出来;
处理内部svg图标显示
处理内部svg图标显示的步骤:
1.首先导入所有的svg图标: 大家可以去我的git仓库直接拷贝src/icons/svg
文件夹到自己的目录下;
2.在icons目录下创建index.js文件,该文件中需要完成两件事情,这个过程类似于Element-plus的导入:
- 导入所有的svg图标;
- 完成SvgIcon的全局注册;
创建icons/svg/index.js
icons/svg/index.js
import SvgIcon from '@/components/SvgIcon'
const svgRequire = require.context('./svg', false, /\.svg$/)
// 返回一个Require函数,可以接受一个request的参数,用于require的导入;
// 该函数提供了三个属性,可以通过svgRequire.keys()获取所有的svg图标;
// 遍历图标,把图标作为request参数传入到svgRequire导入函数中,完成本地svg图标的导入;
svgRequire.keys().forEach((icon) => {
svgRequire(icon)
})
export default (app) => {
app.component('svg-icon', SvgIcon)
}
在main.js中导入;
main.js
// 导入svgIcon
import installIcons from '@/icons'
installIcons(app)
使用svg-sprite-loader处理svg图标
svg-sprite-loader
是webpack中专门用来处理svg图标的一个loader,详情🔎; 我们需要做两件事情:
1.下载该loader,执行
js
npm i svg-sprite-loader@6.0.9 --save
2.创建vue.config.js
文件,新增如下配置,详情🔎:
vue.config.js
const path = require('path')
function resolve(dir) {
return path.join(__dirname, dir)
}
module.exports = {
chainWebapack: (config) => {
// 内置的svg处理排除执行目录下的文件
config.module.rule('svg').exclude.add(resolve('src/icons')).end()
config.module
.rule('svg-sprite-loader')
.test(/\.svg$/)
.include.add(resolve('src/icons'))
.end()
.use('svg-sprite-loader')
.loader('svg-sprite-loader')
.options({
symbolId: 'icon-[name]'
})
.end()
}
}
接着去login页面引入图标组件:
js
<span class="svg-container">
<SvgIcon icon="user"></SvgIcon>
</span>
图标可以正常显示了!