概要
讲解在vue3的项目中封装一个简单好用的图标选择组件。
效果
第一步,准备图标数据
数据太多,大家去项目中看。项目地址https://gitee.com/nideweixiaonuannuande/xt-admin-vue3
第二步,页面与样式编写
<template><div><el-iconclass="icon-picker":class="{ empty: myValue === '' }"@click="dialogVisible = true"><svg-icon :name="myValue !== '' ? myValue : 'ep:plus'" /></el-icon><xt-dialog v-model="dialogVisible" width="800px" title="选择图标" :show-cancel="false" :show-confirm="false"><div><el-tabs v-model="activeName" tab-position="left"><el-tab-panev-for="item in data":key="item.prefix":label="item.name":name="item.prefix"><div class="flex flex-wrap"><divclass="border cursor-pointer border-red-300 p-4"title="删除已选图标"@click="removeIcon"><el-icon :size="24"><svg-icon name="ep:delete" /></el-icon></div><divv-for="icon in currentIconList":key="icon"class="border cursor-pointer p-4"@click="chooseIcon(`${activeName}:${icon}`)"><el-icon :size="24"><svg-icon :name="`${activeName}:${icon}`" /></el-icon></div></div></el-tab-pane></el-tabs><div class="flex mt-4 px-10 justify-end"><el-paginationv-model:current-page="pagination.page"layout="prev, pager, next":page-size="pagination.pageSize":total="iconList.length":pager-count="5"background/></div></div></xt-dialog></div>
</template><style lang="scss" scoped>
.icon-picker {width: 40px;height: 40px;line-height: 36px;text-align: center;color: var(--el-text-color-regular);border: 1px solid var(--el-border-color);border-radius: 5px;cursor: pointer;transition: 0.3s;font-size: 24px;vertical-align: middle;&:hover {border: 1px solid var(--el-border-color-darker);}&.empty {color: var(--el-text-color-placeholder);border: 1px dashed var(--el-border-color);&:hover {color: var(--el-text-color-regular);border: 1px solid var(--el-border-color-darker);}}
}
</style>
第三步,逻辑编写
<script setup lang="ts">
import data from './data/data.json'defineOptions({name: 'IconPicker',
})const props = withDefaults(defineProps<{modelValue: string
}>(), {})const emits = defineEmits(['update:modelValue'])const myValue = computed({get() {return props.modelValue},set(value) {emits('update:modelValue', value)},
})// ------------------数据初始化------------------
const activeName = ref(myValue.value.split(':')[0] || data[0].prefix)const pagination = ref({page: 1,pageSize: 49,
})
const iconList = computed(() => {return data.filter(item => item.prefix === activeName.value)[0].icons
})const currentIconList = computed(() => {return iconList.value.slice((pagination.value.page - 1) * pagination.value.pageSize,(pagination.value.page - 1) * pagination.value.pageSize+ pagination.value.pageSize,)
})// ------------------选择图标相关------------------
const dialogVisible = ref(false)function chooseIcon(val: string) {myValue.value = valdialogVisible.value = false
}function removeIcon() {myValue.value = ''dialogVisible.value = false
}
</script>