element+iconfont 實現iconPicker組件

clipboard.png

在作後臺管理項目的時候,有一個功能是側邊欄可配置。可配置項有:名字、路由、圖標、權限。其中名字、路由、權限在大神的vue-element-admin中已經有很詳細的介紹了,問題就在於icon選擇配置(這個作完以後,發現不是頗有必要,由於這個項目就內部人員在用,配圖表手動輸入class名就ok了),具體方案是用element-ui的select組件自定義模板實現icon可視化選擇。css

功能實現第一步,搜索引擎大法,用baidu、google分別搜索了關鍵詞iconpicker,一大堆搜索結果,有bootstrap的,有layui的,有jquery的。
但他們的icon都是固定的庫,不能本身去增刪改。並且項目中這幾個框架都沒有引入,爲了一個功能去引入一個庫感受有點不划算(庫的OS:誰稀罕你用似的)。vue

搜索無果後,決定本身動手作一個組件,而後先列出本身想要的幾個關鍵點node

icon可維護
增刪icon簡單
圖形化選擇

爲了後期icon的維護(認真思考後感受又是一個不是必要的選項)選擇了用iconfont,能隨時添加刪除icon。
而後圖形化選擇的話,用element-ui自帶的select組件就好了
但問題關鍵在於將iconfont 引入項目
項目引入,直接將iconfont項目下載下來,放到/src/assets/font文件夾中
clipboard.pngjquery

文件卻是放到本地了,但問題是我如何知道我引入了哪些icon,以及將icon的class名輸出到一個數組裏,並在項目中可用。
手動粘貼複製卻是能夠,但下次再增刪幾個icon 還要一一對比嗎?因此條路確定不行了。
如今就是要讀去iconfont.css中的內容,並將其中的因此class提取出來git

clipboard.png

第一個我能想到的方法就是,在vue.config.js中使用node.js的api將iconfont.css的文件內容讀取出來。github

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)
})

代碼確實輸出了iconfont.css中的全部內容element-ui

clipboard.png

而後我須要對這個data進行處理,輸出一個數組bootstrap

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

clipboard.png

提取出icon名,在輸出到一個變量中,但問題是從vue.config.js將變量輸出到哪去,才能在整個項目中使用呢?localstorage中?
並且在開發環境下可以使用node.js 在生產環境可不行。
因此我採起了一個折中的方法,將這個變量輸出到一個文件當中,而後文件中export 這個變量api

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!')
    })
  }
})

replacer 函數來源數組

clipboard.png

接下來就是組件的代碼了

<template>
  <el-select :value="icon" filterable placeholder="請選擇" @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>

// 調用
<icon-picker :icon.sync="icon" />
相關文章
相關標籤/搜索