Vite创建Vue3项目(三)——配置Element Plus+Icons-Vue+Svg自定义图标组件+登录界面+运行地址及端口配置

1,236 阅读3分钟

1.安装Element Plus+

// 选择一个你喜欢的包管理器

//NPM
npm install element-plus --save

//Yarn
yarn add element-plus

//pnpm
pnpm install element-plus

关于使用,因为Element Plus官网介绍已经很详细了,就不赘述了

main.ts文件中引入组件与样式

import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'

createApp(App).use(router).use(store).use(ElementPlus).mount('#app')

按需导入需要额外安装unplugin-vue-components 和 unplugin-auto-import这两款插件

npm install -D unplugin-vue-components unplugin-auto-import

安装好后,在vite.config.ts文件中配置即可

import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'

export default defineConfig({
  plugins: [
    ...
    AutoImport({
      resolvers: [ElementPlusResolver()],
    }),
    Components({
      resolvers: [ElementPlusResolver()],
    })
  ]
})

2.安装Icons-Vue 图标

Element Plus 提供了一套常用的图标集合

//选择一个你喜欢的包管理器

//NPM
npm install @element-plus/icons-vue
//Yarn
yarn add @element-plus/icons-vue
//pnpm
pnpm install @element-plus/icons-vue

main.ts文件中createApp(App)注册所有图标

import * as ElementPlusIconsVue from '@element-plus/icons-vue'

const app = createApp(App)
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
  app.component(key, component)
}

app.use(router).use(store).use(ElementPlus).mount('#app')

页面上使用icon

<el-icon><Plus /></el-icon>

3.Svg自定义图标组件

初始化项目目录

  • 删除assetscomponents 文件夹下的所有.vue 文件

  • 删除根目录下的style.css文件,同时删除main.ts文件中的import './style.css'

  • 在根目录下创建 styles目录及index.scss文件

image.png

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,
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中引入import '@/styles/index.scss'

  • App.vue文件的template中只保留<router-view />

  • 最后在根目录创建views文件夹

创建Svg自定义组件

components文件夹下创建Svgicon文件夹及index.vue文件

Svgicon组件,支持外部图标及项目内部图标

<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" />
  </svg>
</template>

<script lang="ts" setup>
import { isExternal as external } from '@/utils/validate'
import { computed } from 'vue'

interface IProps {
  icon: string
  className?: string
}

const props = withDefaults(defineProps<IProps>(), {})
/**
 * 判断当前图标是否为外部图标
 */
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 {
  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>

main.ts中将组件注册为全局组件

import SvgIcon from '@/components/Svgicon/index.vue'
app.component('SvgIcon', SvgIcon)

在根目录创建icons/svg文件夹,并把svg图标文件放进去

image.png

如何在vue3 + vite 中使用svg图标,首先安装插件vite-plugin-svg-icons

npm i vite-plugin-svg-icons -D

vite.config.ts 中的配置插件

import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
import { resolve } from 'path'

export default () => {
  return {
    plugins: [
      createSvgIconsPlugin({
        // 指定需要缓存的图标文件夹
        iconDirs: [resolve(process.cwd(), 'src/icons/svg')],
        // 指定symbolId格式
        symbolId: 'icon-[dir]-[name]'
      })
    ]
  }
}

src/main.ts 内引入注册脚本

import 'virtual:svg-icons-register'

使用Typescript,在tsconfig.json内添加

// tsconfig.json
{
  "compilerOptions": {
    "types": ["vite-plugin-svg-icons/client"]
  }
}

在组件使用

// 外部图标
<svg-icon icon="https://res.lgdsunday.club/user.svg" />
// 项目内部图标
<svg-icon icon="user" />

4.创建登录界面

  • views文件夹中创建login文件夹并创建index.vue文件

image.png

创建路由

  • router文件夹的index.ts文件中
import { createRouter, createWebHashHistory } from 'vue-router'

/**
 * 公开路由表
 */
const publicRoutes = [
  {
    path: '/login',
    name: 'Login',
    component: () => import('@/views/login/index.vue')
  }
]

const router = createRouter({
  history: createWebHashHistory(),
  routes: publicRoutes
})

export default router

这时候路由的创建就完成了,运行项目在浏览器域名结尾输入login跳转到刚刚生成的路由

image.png

这里会有个eslint的报错提示,原因是根据 ESLint 官方风格指南,除了根组件(App.vue)外,自定义组名称应该由多单词组成(使用大驼峰命名方式或者用“-”连接单词),防止和 html 标签冲突;

这里我们增加一个配置,根据文件进行关闭规则

.eslintrc.cjs文件中的rules中增加

"rules": {
        // 添加组件命名忽略规则
        "vue/multi-word-component-names": ["error",{
            "ignores": ["index"]//需要忽略的组件名
        }]
    }
    
// 或者在`overrides`中增加
// {
//    files: ['src/views/index.vue', 'src/views/**/index.vue'], // 指定的文件
//    rules: { 'vue/multi-word-component-names': 'off' } // 关闭规则
// }

这样登录页就可以正常的打开了。

登录页面的基本布局代码

<template>
  <div class="login-container">
    <el-form class="login-form" :model="loginForm" :rules="loginRules">
      <div class="title-container">
        <h3 class="title">用户登录</h3>
      </div>
      <!--   username   -->
      <el-form-item prop="username">
        <span class="svg-container">
          <svg-icon icon="user" />
        </span>
        <el-input v-model="loginForm.username" placeholder="用户名" name="username" type="text" />
      </el-form-item>
      <!--   password   -->
      <el-form-item prop="password">
        <span class="svg-container">
          <svg-icon icon="password" />
        </span>
        <el-input
          v-model="loginForm.password"
          placeholder="密码"
          name="password"
          type="password"
          show-password
        />
      </el-form-item>
      <!--   登录按钮   -->
      <el-button type="primary" class="login-btn">登录</el-button>
    </el-form>
  </div>
</template>

<script lang="ts" setup>
import { ref } from 'vue'
import { validatePassword } from '@/views/login/rules'
import type { FormRules } from 'element-plus'
// 数据源
const loginForm = ref({
  username: 'super-admin',
  password: '123456'
})
// 校验规则
const loginRules = ref<FormRules>({
  username: [
    {
      required: true,
      trigger: 'blur',
      message: '用户名为必填项'
    }
  ],
  password: [
    {
      required: true,
      trigger: 'blur',
      validator: validatePassword()
    }
  ]
})
</script>

<style lang="scss" scoped>
$bg: #2d3a4b;
$dark_gray: #889aa4;
$light_gary: #eeeeee;
$cursor: #ffffff;

.login-container {
  min-height: 100%;
  width: 100%;
  background-color: $bg;
  overflow: hidden;

  .login-form {
    position: relative;
    width: 520px;
    padding: 160px 35px 0;
    margin: 0 auto;
    overflow: hidden;

    :deep(.el-form-item) {
      border: 1px solid rgba(255, 255, 255, 0.1);
      background-color: rgba(0, 0, 0, 0.1);
      border-radius: 5px;
      color: #454545;
    }

    :deep(.el-input) {
      padding-right: 15px;
      display: inline-block;
      height: 47px;
      flex: 1;

      .el-input__wrapper {
        width: 100%;
        background: transparent;
        border: none;
        -webkit-appearance: none;
        border-radius: 0;
        padding: 8px 5px 8px 15px;
        color: $light_gary;
        caret-color: $cursor;
        box-shadow: none;
      }
    }
  }

  .svg-container {
    padding: 6px 5px 6px 15px;
    color: $dark_gray;
    vertical-align: middle;
    display: inline-block;
  }

  .title-container {
    position: relative;

    .title {
      font-size: 26px;
      color: $light_gary;
      margin: 0px auto 40px;
      text-align: center;
      font-weight: bold;
    }
  }

  .login-btn {
    width: 100%;
    margin-bottom: 30px;
  }
}
</style>

5.开发运行地址及端口配置

vite.config.ts中配置

export default defineConfig({
  server: {
    host: '127.0.0.1'// 指定开发运行应该监听哪个 IP 地址
    port: 8888, // 指定开发运行端口
    open: true //  启动时自动在浏览器中打开应用程序
  },