为什么我不再使用 Element Plus

Element 系列的组件库自 Vue2 出现以来,就已经成为大部分开发者的首选 UI 组件库,直至今天,Element UI 跟 Element Plus 的周下载量都维持在 10w 以上 ,Element 系列组件库相信是大部分 Vue 初学者的入坑首选工具,7 年前,Element-UI 发布了他的第一个版本,但在 7 年后的现在,在搭建新项目时,Vue3 开发者或许应该对 Element Plus 说再见了。

项目背景

Element UI 组件如此受欢迎,我觉的有三点因素

  • 背靠饿了么大厂,有专业团队支持维护
  • 花裤衩大佬 Vue-admin 的开源项目相互成就
  • 培训班教学项目以及大学生课程作业的广告效应

因此,当 Vue 发布了新版本 Vue3 时,为了选取配套的组件库,Element Plus 成为了大部分人的首选。事实上,饿了么官方并没有 Vue3 版本的组件库计划,Element Plus 最初由是作为教培项目展开,后续交给开源工作者维护,这也造成了 Element Plus 的组件设计到后续维护上都存在许多问题。

事实上,我个人对 Element Plus 有着较为复杂的情感,一方面社区大量开源开发者参与其中,推动了 Vue3 生态的发展,相信很多开发者跟我一样,在 GitHub 上的 第一个 PR 是通过 Element Plus 完成的,但另一方面当 Element Plus 落地到公司项目生产,业务对外交付时,很难说它是一个优秀的框架。

项目问题

  • 审美疲劳的 UI 设计

上图是我选取的 Github 上 start 星数比较多的模板项目,不能说这些项目有什么问题,只能说就是那个味。最近的一个月内,我发现了 chrome,网易云都重构了应用的 UI 设计,同样的,或许你也应该给你的项目换换衣服了。

  • 社区大量的 issue

截止今天,Element Plus 仍有 1.3k 的 issue,这些 issue 中有除去建议、讨论跟功能请求,粗略估计还有几百个 bug 仍未解决。

  • 违背常理的默认行为

这里就以我最近遇到的问题为例

1、懒加载树表格全选反选逻辑只针对第一层节点有效

2、 树节点拖拽到树区域外部,drop 事件依然生效

这些问题虽然都不影响组件主流程的运行,但是解决起来很是麻烦,要不阅读源码,要不曲线救国,费一番心思。

  • 积重难返的数据展示组件

直至今天,Element-Plus 的虚拟化功能还不能完全面向生产,同时,我比较想吐槽的一点就是虚拟化表格组件被官方命名 el-table-v2 ,既然有了 v2 是不是后续还会出现 v3、v4、v5?个人只能猜测表格组件为了解决性能问题并不能在原来的组件上很好的兼容向后开发,只能进行 copy 然后 rewrite,同时组件在命名上并没有经过太多的考量而被命名为 v2。

事实上大部分Element Plus 的大部分数据展示组件都会遇到性能问题,比如选择框的下拉选项,树形选择,树表格,这些组件设计之初并没有对性能问题进行规划,之后为了解决这些问题,没有选择在原有的组件添加 prop 去开关虚拟化进行兼容,而是对外开放新的组件。我虽然不可能要求这些数据展示组件能尽可能的满足业务开发需求,但是仅仅作为数据展示组件,这些组件的开发体验仍是不尽人意。

  • 插槽与 JavaScript 之间的割裂感

这点说是 Element-Plus 的问题,倒不如说是使用模板 DSL 的通病,就以表格为例,如何渲染自定义化的 column,用插槽,但是表格列巨多呢,我们就既需要维护模板中的自定义化插槽,又需要维护JavaScript中的业务逻辑,这种割裂感真的十分破坏开发体验。

为此 大部分 Vue 组件库使用 colums 配置 table prop 的方法(这也是大部分开源项目二开 el-table 的思路),减轻这种割裂感

1、 第一种写法,引入 Vue 编译时,使用字符串模板

js 复制代码
 <a-table
      :columns="columns"
   
    />
const columns = computed(() => {
    return [
      {
        title: order,
        render({
          rowIndex,
        }: {
          record: TableData;
          column: TableColumnData;
          rowIndex: number;
        }) {
          const tmp = `<span>${rowIndex + 1}</span>`;
          return h(compile(tmp));
        },
      },
      {
        title:cover,
        render({
          record,
        }: {
          record: TableData;
          column: TableColumnData;
          rowIndex: number;
        }) {
          const tmp = `<div class='data-statistic-list-cover-wrapper'>
              <img src=${record.cover} />
              ${renderTag(record.status)}
            </div>`;
          return h(compile(tmp));
        },
      },
      {
        title: name,
        dataIndex: 'name',
      },
      {
        dataIndex: 'duration',
        title: duration,
      },
      {
        dataIndex: 'id',
        title: id,
      },
    ];
  });

2、 另外一种指定插槽名,然后在模板中自定义渲染列内容

js 复制代码
  <a-table :columns="columns" :data="data">
    <template #name="{ rowIndex }">
      <a-input v-model="data[rowIndex].name" />
    </template>
    <template #province="{ rowIndex }">
      <a-select v-model="data[rowIndex].province" @change="()=>handleChange(rowIndex)">
        <a-option v-for="value of Object.keys(options)">{{value}}</a-option>
      </a-select>
    </template>
    <template #city="{ rowIndex }">
      <a-select :options="options[data[rowIndex].province] || []" v-model="data[rowIndex].city" />
    </template>
  </a-table>


const columns = [{
      title: 'Name',
      dataIndex: 'name',
      slotName: 'name'
    },  {
      title: 'Province',
      dataIndex: 'province',
      slotName: 'province'
    }, {
      title: 'City',
      dataIndex: 'city',
      slotName: 'city'
    }, {
      title: 'Email',
      dataIndex: 'email',
    }];

但事实上,字符串根本不适合进行虚拟DOM 的描述,模板与渲染逻辑的割裂感也不能完全解决,这就是我最近尝试 Vue3 tsx 开发的原因。

工具选取,社区共建

跑远了,无论怎样,我个人都不建议新开项目的时候,将 Element Plus 作为组件工具的首选项了。那么如何寻找替代品呢?我个人内心一直期望 Vue 生态上有一个 ant-design 类似的地位的组件库,无论是 umi 还是 ant-design-pro, 真的让我酸的很。

但没有就是没有,没有只能自己造轮子,Vue 生态下也不少工具值得我们发掘与维护, ant-design-vue 一直在模仿、跟随老大哥的脚步,naive ui 在不少开发者之间广为流传,有了不错的口碑,arco-design 背靠字节系,vuetify 国外团队维护,周下载量能上 50w+,这些工具都具备成为中后台完整工具链的潜质,但在发展的过程中,少不了我们的关注与支持,同时,我个人最近也在尝试将 Vue3 中后台开发中的最佳实践进行总结,期望与大家分享。

如若你不赞同我的说法,也欢迎你加入到 Element Plus 的社区共建之中。

感谢您阅读本文,希望对您有所帮助。如果您觉得本文对您有价值,请点赞并收藏,以便日后查阅。如果您对我的观点有不同的看法或意见,欢迎与我进行交流,谢谢。

相关推荐
黄尚圈圈25 分钟前
Vue 中引入 ECharts 的详细步骤与示例
前端·vue.js·echarts
浮华似水1 小时前
简洁之道 - React Hook Form
前端
正小安3 小时前
如何在微信小程序中实现分包加载和预下载
前端·微信小程序·小程序
_.Switch5 小时前
Python Web 应用中的 API 网关集成与优化
开发语言·前端·后端·python·架构·log4j
一路向前的月光5 小时前
Vue2中的监听和计算属性的区别
前端·javascript·vue.js
长路 ㅤ   5 小时前
vite学习教程06、vite.config.js配置
前端·vite配置·端口设置·本地开发
长路 ㅤ   5 小时前
vue-live2d看板娘集成方案设计使用教程
前端·javascript·vue.js·live2d
Fan_web5 小时前
jQuery——事件委托
开发语言·前端·javascript·css·jquery
安冬的码畜日常5 小时前
【CSS in Depth 2 精译_044】第七章 响应式设计概述
前端·css·css3·html5·响应式设计·响应式
莹雨潇潇6 小时前
Docker 快速入门(Ubuntu版)
java·前端·docker·容器