图标选择器
架构
bash
├── src
│ ├── components
│ │ ├── chooseIcon
│ │ │ ├── lib (引入的第三方库)
│ │ │ │ └── xxx.json
│ │ │ ├── src (源码)
│ │ │ │ ├── index.vue
│ │ │ ├── index.ts
index.ts
ts
import { type App } from 'vue'
import chooseIcon from './src/index.vue'
// 让这个组件可以通过use的形式使用
export default {
install(app: App) {
app.component('YJ-choose-icon', chooseIcon)
}
}
hooks/chooseIcon/useIcon
- useIcon.ts
ts
import { ElMessage } from 'element-plus'
export const useIcon = () => {
// 写一个方法复制内容到剪贴板
const copyToClipboard = (text: string, callback: (arg: boolean) => void) => {
navigator.clipboard
.writeText(text)
.then(() => {
ElMessage.success('复制成功')
callback(false)
})
.catch(error => {
ElMessage.error('复制失败')
callback(false)
})
}
return {
copyToClipboard
}
}
类型
- interfaces/chooseIcon/type.ts
ts
export interface Idata {
title: String
visible: Boolean
width: Number
height: Number
}
src/index.vue
Object as PropType<Idata>
这个类型是ts的语法,表示将对象类型转换为Idata类型
vue
<template>
<div>
<el-button type="primary" @click="changevisable(true)">
<slot></slot>
</el-button>
<!--弹出框开始-->
<el-dialog
v-model="props.data.visible"
:title="props.data.title"
:width="props.data.width"
:height="props.data.height"
>
<el-scrollbar :height="props.data.height">
<div class="icon-list">
<div v-for="item in iconList" :key="item" class="icon-item">
<div class="icon" @click="chooseIcon(item)">
<el-icon :size="30">
<component :is="item"></component>
</el-icon>
<div>{{ item }}</div>
</div>
</div>
</div>
</el-scrollbar>
</el-dialog>
<!--弹出框结束-->
</div>
</template>
<script setup lang="ts">
import { defineProps, defineEmits, defineExpose, ref, watch, computed, type PropType } from 'vue'
import { type Idata } from '@/interfaces/chooseIcon/type'
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
import { toLine } from '@/utils/tools'
import { useIcon } from '@/hooks/chooseIcon/useIcon'
const { copyToClipboard } = useIcon()
const props = defineProps({
data: {
type: Object as PropType<Idata>,
required: true
}
})
// 改变父元素
const emits = defineEmits(['changedatavisible'])
const changevisable = (content: boolean) => {
emits('changedatavisible', content)
}
// 图标列表
const iconList = computed(() => {
const result = []
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
result.push(`el-icon${toLine(key)}`)
}
return result
})
// 选择图标,传递进来回调函数
const chooseIcon = (icon: string) => {
let text = `<${icon}></${icon}>`
copyToClipboard(text, changevisable)
}
</script>
<style scoped lang="scss">
.icon-list {
display: flex;
flex-wrap: wrap;
.icon-item {
width: 25%;
height: 100px;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
.icon {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
}
}
</style>
父元素调用
vue
<template>
<div>
图标选择
<YJ-choose-icon :data="data" @changedatavisible="changevisible">
选择图标
<el-icon-setting class="el-icon--right"></el-icon-setting>
</YJ-choose-icon>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { type Idata } from '@/interfaces/chooseIcon/type'
const data = ref<Idata>({
title: '图标选择',
visible: true,
width: 800,
height: 450
})
const changevisible = (content: boolean) => {
data.value.visible = content
}
</script>
<style scoped></style>