封装组件库-图标选择器

2023, Feb 20    

实现图标选择器

基于Element-plus框架的Icon图标,封装为图标选择器。

初始配置

  • 注册路由组件chooseIcon,配置为Container组件的子路由组件
  • 采用路由懒加载,箭头函数异步引入组件。
  • 注册通用组件ChooseIcon,为路由组件的子组件,以便组件间通信。

ChooseIcon组件

ChooseIcon组件采用Element-plus的Button组件和Dialog对话框组件,引入Icon图标,实现选择器功能。 Dialog对话框存在v-model属性,值为boolean类型,初始为false,控制对话框的显示与隐藏。

  <el-dialog :title="title" v-model="dialogVisible">

父组件给子组件传递tilte和visible

  <choose-icon title="选择图标" v-model:visible="visible">选择图标</choose-icon>
  let visible = ref<boolean>(false) 

子组件props接收,并拷贝,传递给模版

 <el-dialog :title="title" v-model="dialogVisible">
 let props = defineProps<{
    //弹出框的标题
    title: string,
    //显示与隐藏
    visible: boolean,
 }>()
 //拷贝props的visible
 let dialogVisible = ref<boolean>(props.visible)

问题

初始化的visible值为false,点击按钮后,给父组件传递true。同时给props.visible开启watch监听,dialogVisible.value = true。

  <el-button @click="handleClick" type="primary">
  let emits = defineEmits(['update:visible'])
  //  关闭遮罩层后,visible值为false,没有点击按钮,捕获不到事件
  let handleClick = ()=>{
    emits('update:visible', !props.visible)
  }
  //只能监听一次变化
  watch(()=> props.visible,val => {
    dialogVisible.value = val
  })

此时观察父组件visible的变化发现,关闭对话框后,visible的值依然为true,而子组件的内部,由于关闭了对话框,dialogVisible的值变为了false。 因此,可以将dialogVisible的值传递给父组件,用来更新visible的值。则开启二次监听,对dialogVisible进行监听。

  //对组件内部的dialogVisible进行监听
  watch(()=> dialogVisible.value, val => {
    emits('update:visible', val)
    // console.log(val);
  })

图标引入

引入所有图标,在对话框内呈现

  import * as Icons from '@element-plus/icons'
  <div class='item' 
    v-for="(item,index) in Object.keys(Icons)" 
    :key='index'
    @click="clickItem(item)">
    <div>
      <component :is="`qt-icon-${toLine(item)}`"></component>
    </div>
    <div></div>
   </div>

v-for遍历图标对象的键名,同时采用动态组件进行渲染。同时,设置图标的名称,toLine方法用来将驼峰名改为横线分割。 图标组件的名称为 qt-icon-xxx

  export const toLine = (value: string)=>{
      return value.replace(/(A-Z)g/, '-$1').toLocaleLowerCase()
  }

图标复制功能

此时,需要实现点击icon图标,useCopy复制其名称。并且,复制完成后,关闭对话框。

  let clickItem = (item: string)=>{
    let text = `<qt-icon-${toLine(item)}/>`
    useCopy(text)
    dialogVisible.value = false
  }

定义一个hooks,实现useCopy方法。思想:在文档定义一个input框,值为传参,放入文档。选中对话框,execCommand(‘Copy’)复制,最后删除对话框。

  import { ElMessage } from "element-plus"
  //复制文本,利用文本框
  export const useCopy = (text: string)=>{
    let input = document.createElement('input')
    input.value = text
    document.body.appendChild(input)
    //选中输入框
    input.select()
    //执行复制操作
    document.execCommand('Copy')
    document.body.removeChild(input)
    ElMessage.success('复制成功')
  }

图标样式

Element-plus阻止了样式的修改,因此需要自定义一个类名空间,在App.vue内注册,并在修改样式的元素的父元素添加类名

  .choose-icon-dialog-body-height{
    .el-dialog__body{
      height: 500px;
      overflow: scroll;
    }
  }