element+iconfont Implementing iconPicker Component

Keywords: Javascript Vue Google JQuery

When doing background management projects, there is a function that the sidebar can be configured. Configurable items are: name, routing, icon, permission. The name, routing, and authority are in God's vue-element-admin The problem is that the icon selection configuration (after this, it is not necessary, because the project is used by the internal staff, and the class name is input manually by the matching chart), the specific solution is to use the element-ui selector component custom template to realize icon visual selection.

The first step to realize the function is search engine method, which uses baidu and google to search keywords iconpicker respectively. There are a lot of search results, including bootstrap, layui and jquery.
But their icon s are fixed libraries and cannot be added or deleted by themselves. And none of these frameworks have been introduced in the project, so it's a bit inexpensive to introduce a library for a function (OS of the library: Who rarely uses it like you).

After unsuccessful search, decide to make a component by yourself, and then list the key points you want first.

icon maintainable
Simple to add or delete icon
Graphical selection

In order to maintain the icon in the later stage (after careful consideration, it feels like it is not a necessary option), we choose to use iconfont, which can add and delete icon at any time.
Then, if you choose graphically, use the select component that comes with element-ui.
But the key is to introduce iconfont into the project
Project introduction, download the iconfont project directly and place it in the / src/assets/font folder

The file is localized, but the problem is how do I know which icons I introduced, and how to output the class name of icon to an array and make it available in the project.
It's okay to paste and copy manually, but do you need to compare them one by one next time you add or delete a few icon s? So the road is definitely not going to work.
Now it's time to read the iconfont.css and extract the class es from it.

The first way I can think of is to use the api of node.js in vue.config.js to read out the contents of iconfont.css files.

const path = require('path')
const rf = require('fs')
function resolve (dir) {
  return path.join(__dirname, dir)
}
rf.readFile(resolve('src/assets/font/iconfont.css'), 'utf-8', function (err, data) {
  if (err) {
    console.log('error')
    return false
  } else {
    console.log(data)
})

The code does output everything in iconfont.css

Then I need to process the data and output an array.

const res = data.match(/.iconfont*.+:before/g)

Extract the icon name and output it to a variable, but the question is where to export the variable from vue.config.js to use it in the whole project? In local storage?
In addition, it is not feasible to use node.js in the development environment in the production environment.
So I took a compromise approach, output this variable to a file, and then export this variable in the file.


function replacer (match, p1, p2, p3, offset, string) {
  // p1 is nondigits, p2 digits, and p3 non-alphanumerics
  return p2
}
rf.readFile(resolve('src/assets/font/iconfont.1.css'), 'utf-8', function (err, data) {
  if (err) {
    console.log('error')
    return false
  } else {
    const res = data.match(/.iconfont*.+:before/g)
    icondata = res.map(item => {
      return `'${item.replace(/(.iconfont-)(.*)(:before)/, replacer)}'`
    })
    icondata = `export default [${icondata.toString()}]`
    rf.writeFile(resolve('src/utils/icon.js'), icondata, (err) => {
      if (err) throw err
      console.log('The file has been saved!')
    })
  }
})

Source of replacer function

Next is the component code.

<template>
  <el-select :value="icon" filterable placeholder="Please choose" @change="handleChange">
    <el-option
      v-for="item in icons"
      :key="item"
      :label="item"
      :value="item">
      <span style="float: left"><i class="iconfont" :class="`iconfont-${item}`"></i></span>
      <span style="float: right; color: #8492a6; font-size: 13px">{{ item }}</span>
    </el-option>
  </el-select>
</template>
<script>
import icons from '@/utils/icon'
export default {
  props: {
    icon: {
      type: String,
      default: ""
    }
  },
  data () {
    return {
      icons,
    }
  },
  methods: {
    handleChange(val){
      this.$emit('update:icon',val)
    }
  },
}
</script>

// call
<icon-picker :icon.sync="icon" />

Posted by rd321 on Tue, 23 Apr 2019 10:39:34 -0700