此为demo练习记录,个人思路二次整理,如有不当欢迎指正
一. 实现 图标选择器 组件封装的步骤简述
- 全局注册 element-plus 的icon组件
- 创建 ChooseIcon.vue 组件
- . 引入element-plus的 icons
- . 渲染 icon 组件
- . 实现 copy 方法
二 . 全局注册 element-plus 的icon组件
参考element-plus 官网: https://element-plus.gitee.io/zh-CN/component/icon.html
- 在main.ts中 从"@element-plus/icons-vue" 中导入所有图标并进行全局注册
- 创建 utils/index.ts 文件 创建方法 (toLine) , 将icon组件转驼峰命名
import * as Icons from "@element-plus/icons-vue";
for (const [key, component] of Object.entries(Icons)) {
app.component(`el-icon-${toLine(key)}`, component)
}
export const toLine = (v: string) => {
return v.replace(/([a-z])([A-Z])/g, '$1-$2').toLocaleLowerCase();
};
```typescript
转换 结果 如下图所示 :
转换前: 转换后: 正则解读 :
([a-z])和([A-Z])正好匹配小写,大写字母; g : 全局匹配 $1表示匹配的第一个小括号里的 ,$2是匹配的第2个小括号里的内容 见示例
let str = 'AaaBbCcDdEe'
let test = str.replace(/([a-z])([A-Z])/g, '$1-$2')
console.log(test, 'test')
三 . 创建 components/ChooseIcon.vue组件
目录结构 : components
- ChooseIcon/index.vue :
<template>
<el-button :type="type" @click="handleClick">
<slot>{{ buttonText }}</slot>
</el-button>
<copy-icons title="图标选择器" v-model:visible="visible" />
</template>
<script setup lang="ts">
import { defineProps, ref } from 'vue'
import copyIcons from './components/copyIcons.vue'
let props = defineProps({
buttonText: {
type: String,
default: '',
},
type: {
type: String,
default: 'primary',
},
})
let visible = ref<boolean>(false)
const handleClick = () => {
visible.value = true
}
</script>
- ChooseIcon/components/CopyIcons.vue :
<template>
<el-dialog draggable :model-value="visible" :title="title" width="42%" @close="handleClose">
<el-scrollbar height="400px">
<div class="icons-container">
<div v-for="(v, i) in Object.keys(Icons)" :key="i" class="icon">
<component :is="`el-icon-${toLine(v)}`"></component>
<span class="icon-text"> {{ `el-icon-${toLine(v)}` }}</span>
</div>
</div>
</el-scrollbar>
</el-dialog>
</template>
<script setup lang="ts">
import { defineProps, defineEmits } from 'vue'
import * as Icons from '@element-plus/icons-vue'
import { toLine } from '@/utils'
let props = defineProps({
title: {
type: String,
default: '选择图标',
},
visible: {
type: Boolean,
default: false,
},
})
const emits = defineEmits(['update:visible'])
const handleClose = () => {
emits('update:visible', false)
}
</script>
<style scoped lang="scss">
::v-deep .el-dialog__body {
height: 400px !important;
overflow-y: scroll;
}
.icons-container {
display: flex;
flex-wrap: wrap;
.icon {
width: 25%;
height: 60px;
display: flex;
flex-direction: column;
align-items: center;
padding: 0 5px;
box-sizing: border-box;
cursor: pointer;
.icon-text {
flex: 1;
font-size: 12px;
}
&:hover {
color: #409efa;
}
}
svg {
width: 1.5em;
height: 1.5em;
}
}
</style>
四.实现 copy 方法
- hooks/index.ts
import { ElMessage } from 'element-plus'
export const copy = (text: string, tips: string) => {
let input = document.createElement('input')
input.value = text
document.body.appendChild(input)
input.select()
document.execCommand('copy')
ElMessage.success(tips)
document.body.removeChild(input)
}
- 完善 CopyIcons组件代码
<template>
<el-dialog draggable :model-value="visible" :title="title" width="42%" @close="handleClose">
<el-scrollbar height="400px">
<div class="icons-container">
<div v-for="(v, i) in Object.keys(Icons)" :key="i" class="icon" @click="copyIcon(v)">
<component :is="`el-icon-${toLine(v)}`"></component>
<span class="icon-text"> {{ `el-icon-${toLine(v)}` }}</span>
</div>
</div>
</el-scrollbar>
</el-dialog>
</template>
<script setup lang="ts">
import { copy } from '@/hooks'
const copyIcon = (v: string) => {
const tagName = `<el-icon-${toLine(v)} />`
copy(tagName, '标签复制成功')
handleClose()
}
</script>
- 单页面内使用
<template>
<div>
<choose-icon buttonText="选择图标" />
</div>
</template>
<script setup lang="ts">
import ChooseIcon from '@/components/ChooseIcon/index.vue'
</script>
五. 效果展示
六. 总结
提示:以上为 vue3 封装 图标选择器功能实现完整记录 ,如有不当以及不清晰之处欢迎评论区交流;
|