在维护公司内部UI库时,某些场景需要进行图标选择,去UI库中寻找显然不符合用户需求,这时候就需要封装一个图标选择器组件。

先定义一个触发框,可以用el-input,我这里使用的是基于el-input封装的输入框组件。然后使用el-popover组件进行嵌套

<template>
  <div>
    <el-popover
        ref="popover"
        placement="bottom"
        popper-class="iconPicker vxe-table--ignore-clear"
        :width="popperWidth"
        :visible-arrow="false"
        transition="el-zoom-in-top"
        trigger="click">
      <el-scrollbar style="height: 300px">
        <div class="mainBox">
          <ul class="icon-list" >
            <li v-for="icon in iconList" :key="icon" class="icon" >
              <i :class="[icon,{'checked': icon === checked}]"  @click="handleClick(icon)"></i>
            </li>
          </ul>
        </div>

      </el-scrollbar>
      <div slot="reference" class="triggerBox">
        <el-input :size="size" readonly class="trigger" v-model="checked"></el-input>
      </div>
    </el-popover>
  </div>
</template>

图标库我们是在阿里图标库进行的上传和维护,下载字体图标文件时,将iconfont.json文件也复制进项目中,在图标选择器内进行引入。

<script>
const json = require("../../packages/assets/iconfont/iconfont.json")
export default {
  name: "iconPicker",
  props: {
    value: String,
    size: String,
  },
  data() {
    return {
      popperWidth: 400,
      checked: this.value
    }
  },
  watch: {
    value(val) {
      this.checked = val;
    }
  },
  computed: {
  	// 利用json文件组装图标
    iconList() {
      return this.json2FontClass(json).list;
    }
  },
  mounted() {
  	// 下拉面板宽度跟随input框宽度
    let trigger = this.$el.querySelector(".trigger");
    this.popperWidth = trigger.offsetWidth;
  },
  methods: {
    handleClick(icon) {
      this.$refs.popover.doClose();
      this.checked = icon;
      this.$emit("change", icon)
      this.$emit("input", icon)
    },
    json2FontClass(json) {
      let font_family = '';
      let css_prefix_text = '';
      let list = [];
      if (json) {
        if (json.font_family) {
          font_family = json.font_family;
        }
        if (json.css_prefix_text) {
          css_prefix_text = json.css_prefix_text;
        }
        if (json.glyphs) {
          list = json.glyphs.map((value) => font_family + " " + css_prefix_text + value.font_class);
        }
      }
      return {
        font_family: font_family,
        css_prefix_text: css_prefix_text,
        list: list
      };
    }
  }
}
</script>

样式文件

<style lang="scss" scoped>
::v-deep{
  .el-scrollbar__bar.is-horizontal{
    display: none;
  }
  .el-scrollbar__wrap{
    overflow-x: hidden;
  }
}
.mainBox{
  padding: 8px;
}
.icon-list{
  list-style-type: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: space-around;
  gap: 8px;
  li {
    width: 30px;
    height: 30px;
    display: flex;
    justify-content: center;
    align-items: center;
    i, svg, div {
      font-size: 16px;
      cursor: pointer;
    }
    .checked{
      color: #3F8CFF;
    }
  }

  &::after {
    content: '';
    flex: auto;
  }
}
.triggerBox{
  &:hover{
    cursor: pointer;
  }
  .trigger{
    pointer-events: none;
  }
}

</style>
<style lang="scss">
.iconPicker.el-popper{
  padding: 0;
  border-radius: 12px;
}
</style>

至此,图标选择器封装完毕。同理还可以利用popover来封装其他下拉组件,比如下拉树形选择器等。

感谢观看。