ElementUI和Ant Design對比

之前先接觸了ElementUI,然后后面又接觸了Ant Design,在這里做個對比,希望通過對比這兩前端ui框架,能夠更加深入的了解和使用這些框架。

表格對比

????首先,通過一張表格來對比這兩框架的異同吧

對比項 ElementUI Ant Design
logo
官網(wǎng)/文檔 vue: https://element.eleme.cn vue: https://www.antdv.com/docs/vue
react: https://ant.design/docs/react/introduce-cn
團隊 餓了么 螞蟻金服
簡介 基于 Vue 2.0 的桌面端組件庫 開發(fā)和服務于企業(yè)級后臺產(chǎn)品
最新版本 vue: 2.13.1 vue: 1.5.3
react: 4.1.4
組件前綴 el- a-
github vue: https://github.com/ElemeFE/element vue: https://github.com/vueComponent/ant-design-vue
react: https://github.com/ant-design/ant-design
start/fork vue: 44.8k/10.3k vue: 10k/1.4k
react: 58.8k/21.5k
pro版 https://github.com/PanJiaChen/vue-element-admin https://pro.ant.design/

個人感受

????從體驗上來看:

我更加傾向于elementUI, UI上更加漂亮,使用起來更加容易上手。
一開始,我最新接觸的就是elementUI,感覺elementUI這個框架更加適合于面向外部開發(fā)。

而作為對比的Ant Design,也有一定的優(yōu)勢。
從功能上來講,后者更加齊全。比如回到頂部組件:樹形選擇:<a-tree-select />Ant Design更加適合管理平臺的開發(fā)。

????從實用上來看:

對于pro版本,vue-element-admin允許初始化基礎版,而ant-design-pro這個初始化后有大量的例子,開發(fā)之前還得把例子刪掉,這點感覺不太好。
總之,兩個框架的pro版本做的都非常棒,但個人更加傾向于ant-design,畢竟組件多占有非常大的優(yōu)勢。

????總之:

如果是想快速上手,又希望ui更加漂亮,建議用elementUI;如追求的是比較復雜的后臺管理平臺,可以考慮采用ant-design-pro,而且ant-design-pro無論表格還是表單,都是高度可配置化的。這點相對于elementUI來說,ant-design-pro雖然稍微復雜了點,但是換來更大的便利。

一些建議和經(jīng)驗

以下代碼部分都是vue,不涉及react

1. elementUI的菜單組件<el-dropdown>在手機端點擊會回彈的問題

修改triggerclick的方式,因為默認hover時,手機上并不能有很好的體驗。

2. elementUI如何實現(xiàn)通用表單的配置

采用form-create這個庫可以很方便的實現(xiàn)表單完全的json配置

主頁:http://www.form-create.com/
git地址:https://github.com/xaboy/form-create

另外還有一種方式,就是利用Vue的插槽實現(xiàn),這種方式也適合ant-design的可配置表單的實現(xiàn)。

ps: 注意插槽名稱不要帶數(shù)字,最好不要

下面是利用插槽實現(xiàn)可配置的例子,這里以ant-design為例:

form.json

{
  "props": {
    "layout": "inline"
  },
  "dataSource": [
    {
      "label": "咨詢ID",
      "cmp": "Input",
      "decorator": ["qaId", { "initialValue": "" }],
      "props": {
        "allowClear": true
      }
    }
]

然后是編寫通用表單組件:
分為兩個文件:baseForm.vue和commonForm.vue,對外使用commonForm.vue即可:

baseForm.vue

<template>
  <a-form v-bind="props" :form="form" @submit="onSubmit">
    <template v-for="item in dataSource">
      <a-form-item :key="item.key" :label="item.label">
        <slot :name="item.cmp" :item="item" :form="props.name"> </slot>
      </a-form-item>
    </template>
    <slot name="footer">
      <a-form-item label>
        <a-button type="primary" html-type="submit"> 提交 </a-button>
      </a-form-item>
    </slot>
  </a-form>
</template>
<script>
export default {
  props: {
    props: {
      type: Object,
      default() {
        return {}
      }
    },
    dataSource: {
      type: Array,
      default() {
        return []
      }
    }
  },
  data() {
    return {
      form: this.$form.createForm(this, { name: ’base-form‘ })
    }
  },
  methods: {
    handleReset() {
      this.form.resetFields()
    },
    validate() {
      this.form.validateFields({ force: true }, () => {})
    },
    getFields() {
      return new Promise((resolve, reject) => {
        this.form.validateFields({ force: true }, (err, values) => {
          if (err) {
            reject(err)
            return
          }
          resolve(values)
        })
      })
    },
    onSubmit(e) {
      e && e.preventDefault()
      this.form.validateFields((err, values) => {
        if (!err) {
          this.$emit('change', values)
        }
      })
    }
  }
}
</script>

commonForm.vue

<template>
  <div v-if="dataSource.length">
    <base-form
      ref="form"
      :props="props"
      :dataSource="dataSource"
      @change="change"
    >
      <template v-slot:Input="{ item }">
        <a-input v-decorator="item.decorator" v-bind="item.props" v-on="item.events" />
      </template>
      <template v-slot:Radio="{ item }">
        <a-radio v-decorator="item.decorator" v-bind="item.props" v-on="item.events" />
      </template>
      <template v-slot:RadioGroup="{ item }">
        <a-radio-group v-decorator="item.decorator" :options="item.options" v-bind="item.props" v-on="item.events" />
      </template>
      <template v-slot:Switch="{ item }">
        <a-switch v-decorator="item.decorator" v-bind="item.props" v-on="item.events" />
      </template>
      <template v-slot:DatePicker="{ item }">
        <a-date-picker v-decorator="item.decorator" v-bind="item.props" v-on="item.events" />
      </template>
      <template v-slot:Checkbox="{ item }">
        <a-checkbox v-decorator="item.decorator" v-bind="item.props" v-on="item.events" />
      </template>
      <template v-slot:CheckboxGroup="{ item }">
        <a-checkbox-group v-decorator="item.decorator" :options="item.options" v-bind="item.props" v-on="item.events" />
      </template>
      <template v-slot:Select="{ item }">
        <a-select v-decorator="item.decorator" v-bind="item.props" :options="item.options" v-on="item.events" />
      </template>
    </base-form>
  </div>
</template>
<script>
export default {
  props: {
    value: {
      type: Object,
      default() {
        return {}
      }
    },
    props: {
      type: Object,
      default() {
        return {}
      }
    },
    dataSource: {
      type: Array,
      default() {
        return []
      }
    }
  },
  components: {
    BaseForm: () => import('./BaseForm')
  },
  model: {
    prop: 'value',
    event: 'change'
  },
  methods: {
    reset() {
      this.$refs.form.handleReset()
    },
    validate() {
      this.$refs.form.validate()
    },
    getFields() {
      return this.$refs.form.getFields()
    },
    isExistedSlot(name) {
      return this.registedSlot.includes(name)
    },
    change(values) {
      this.$emit('change', values)
    }
  }
}
</script>

ps: 這里需要注意v-bindv-on,平時我們都是用:<屬性名稱>以及@<事件名稱>,而這里屬性和事件并不是固定的,通過v-bind="props"以及v-on="events"可以批量的不固定的設置屬性和事件

3. 關于手動文件上傳

注意,ant-design中,file對象可以通過綁定<a-upload-dragger :beforeUpload="beforeUpload" />beforeUpload方法得到。

export default {
  methods:{
    importDoc(data, file, progress) {
           return this.$axios({
            url: '<上傳地址>',
            method: 'post',
            headers: { 'Content-Type': 'multipart/form-data' },
            onUploadProgress: function(progressEvent) {
            const complete = ((progressEvent.loaded / progressEvent.total) * 100) | 0
            progress(file, complete)
            },
            data
        })
    }
  },
upload(file){
  var formData = new FormData()
        formData.append('file', file)
        file.status = 'uploading'
        const res = await importDoc(formData, file, this.progress)
        file.status = 'success'
  }
}

4. Ant Design表單自定義組件,且支持校驗

實際上這個很好做:

export default {
  props:['value'],
  model:{ prop: 'value', event: 'change' },
  methods:{
    changeValue(value){
      this.$emit('change', value)
    }
  }
}

這里需要注意,屬性只能是value,這樣也同時支持了valuev-model。然后假設有自定義組件demo.vue,則該表單組件可以這樣寫:

<demo v-decorator="['demo',{ 'initialValue': '', rules:[ { required: true, message: '請輸入demo' } ] }]" />

5. store文件夾下的狀態(tài)管理中,modules文件夾下所有文件的自動引入

這個可以采納vue-element-admin中的寫法:

替換strore/index.vue文件:

import Vue from 'vue'
import Vuex from 'vuex'
import getters from './getters'
Vue.use(Vuex)
const modulesFiles = require.context('./modules', true, /\.js$/)
// 遍歷modules文件
const modules = modulesFiles.keys().reduce((modules, modulePath) => {
  const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')
  const value = modulesFiles(modulePath)
  modules[moduleName] = value.default
  return modules
}, {})
const store = new Vuex.Store({
  modules,
  getters
})
export default store

這里需要注意,strore/modules下的文件不一定都是狀態(tài)文件,所以可以對于value進行進一步判斷,比如說判斷value是否存在,是否有state這個屬性。

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,316評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,481評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,241評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,939評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,697評論 6 409
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,182評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,247評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,406評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,933評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,772評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,973評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,516評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,209評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,638評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,866評論 1 285
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,644評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,953評論 2 373

推薦閱讀更多精彩內(nèi)容