前端组件高级封装技巧--纯干货

对于前端的小伙伴来说,最常见的工作就是写后台管理系统的页面,而后台管理系统最多的操作就是CRUD了,类似下面的,一个搜索框,一个表格,一个分页,然后点击新增编辑有个弹框

当你写过一段时间的CRUD,就会发现其中很多代码都是重复的,变动的不过是接口地址,搜索条件,表格列的属性等。这时你肯定想,把这些变动的独立出来,写成一个配置json对象,页面根据这个配置对象生成,不是省事很多。

如果你初出茅庐,我会说小伙子不错,有想法,如果你已经工作过一段时间还有这种想法,我只能无奈的说,图样图森破。

基于配置生成页面有个最大的缺陷是不够灵活,只要需求有点变动就要修改生成方法,比如前提表格都是文字,那你配置文件里面只要配置字段名就行了,但如果表格里面要显示图片,麻烦就来了,你要在配置文件里面加个类型,然后改动生成逻辑,如果如上图所示还要再表格里加个按钮,我估计你头都要大了。按照设计模式来说,这种方式违反了开闭原则。

我见过好几个使用了基于配置的项目,最后无一例外的陷入了维护地狱,只能让原来搭建框架的人来维护,新人很难上手,要改动一点东西都要改好久。这是一个大坑,不要去踩!

基于配置生成组件只适用于局部组件,并且是后期基本不会去改动的组件。

最好的封装方式还是基于组件的方式,特别是render函数,用好了特别方便。

下面分享一个小案例,搜索框一般一行4个,使用el-row, el-col来布局,每4个搜索条件套一层el-row,再在每个搜索条件上面套一层el-col,写起来就很繁琐,类似下面

html 复制代码
<el-row>
    <el-col>
        <ui-text v-model="searchParams.q_username_like" label="用户名"/>
    </el-col>
    <el-col>
        <ui-select v-model="searchParams.q_enabled_eq" label="状态" :items="valueCommon.enabledType"/>
     </el-col>
     <el-col>
        <div>
           <ui-button operateType="search" @click="handleSearch"></ui-button>
           <ui-button operateType="reset" @click="handleReset"></ui-button>
         </div>
      </el-col>
</el-row>

有没有办法可以自动套上el-row和el-col呢?这就要使用render函数了

我们封装一个组件叫ui-row

html 复制代码
<script lang="ts">
// @ts-nocheck

export default {
  name: "ui-row",
  render() {
    let vRows = [] // 行节点
    let vCols = [] // 列节点
    let slots = this.$slots.default({})
    let countSpan = 0
    let colIndex = 0
    vCols[colIndex] = []
    for (let n = 0; n < slots.length; n++) {
      let ctl = slots[n]
      let span = this.getSpan(ctl)
      vCols[colIndex].push(h(ElCol, {span}, {
        default: () => {
          return ctl
        },
      }))
      let nextSpan = 0;
      if (n + 1 < slots.length) {
        nextSpan = this.getSpan(slots[n + 1])
      }
      countSpan += span
      // 生成行
      if (nextSpan == 0 || countSpan == 24 || countSpan + nextSpan > 24) {
        vRows.push(h(ElRow, null, {
          default: (index => {
            return () => {
              return vCols[index]
            }
          })(colIndex),
        }))
        countSpan = 0
        vCols[++colIndex] = []
      }
    }
    return h('div', null, vRows)
  },
  methods: {
    getSpan(ctl) {
      let span = 6
      if (ctl.props && ctl.props.span) {
        span = ctl.props.span
      }
      return span
    }
  }
}
</script>

<style scoped>

</style>

优化后的代码

html 复制代码
<ui-row>
    <ui-text v-model="searchParams.q_username_like" label="用户名"/>
    <ui-select v-model="searchParams.q_enabled_eq" label="状态" :items="valueCommon.enabledType"/>
    <div>
      <ui-button operateType="search" @click="handleSearch"></ui-button>
      <ui-button operateType="reset" @click="handleReset"></ui-button>
     </div>
</ui-row>
相关推荐
前端大卫24 分钟前
Vue3 + Element-Plus 自定义虚拟表格滚动实现方案【附源码】
前端
却尘40 分钟前
Next.js 请求最佳实践 - vercel 2026一月发布指南
前端·react.js·next.js
ccnocare41 分钟前
浅浅看一下设计模式
前端
Lee川1 小时前
🎬 从标签到屏幕:揭秘现代网页构建与适配之道
前端·面试
Ticnix1 小时前
ECharts初始化、销毁、resize 适配组件封装(含完整封装代码)
前端·echarts
纯爱掌门人1 小时前
终焉轮回里,藏着 AI 与人类的答案
前端·人工智能·aigc
twl1 小时前
OpenClaw 深度技术解析
前端
崔庆才丨静觅1 小时前
比官方便宜一半以上!Grok API 申请及使用
前端
星光不问赶路人2 小时前
vue3使用jsx语法详解
前端·vue.js
天蓝色的鱼鱼2 小时前
shadcn/ui,给你一个真正可控的UI组件库
前端