vue3+ts封装图标选择组件

概要

讲解在vue3的项目中封装一个简单好用的图标选择组件。

效果

在这里插入图片描述

第一步,准备图标数据

数据太多,大家去项目中看。项目地址https://gitee.com/nideweixiaonuannuande/xt-admin-vue3
在这里插入图片描述

第二步,页面与样式编写

<template>
  <div>
    <el-icon
      class="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-pane
            v-for="item in data"
            :key="item.prefix"
            :label="item.name"
            :name="item.prefix"
          >
            <div class="flex flex-wrap">
              <div
                class="border cursor-pointer border-red-300 p-4"
                title="删除已选图标"
                @click="removeIcon"
              >
                <el-icon :size="24">
                  <svg-icon name="ep:delete" />
                </el-icon>
              </div>
              <div
                v-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-pagination
            v-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 = val
  dialogVisible.value = false
}

function removeIcon() {
  myValue.value = ''
  dialogVisible.value = false
}
</script>

写在最后

这个组件中涉及到的svg-icon和xt-dialog组件大家可前往https://gitee.com/nideweixiaonuannuande/xt-admin-vue3中查看源代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值