ElementUI 组件按需封装

2022-07-29 09:40:56 浏览数 (3)

前言

公司用了好几个年的核心业务系统今年升级重写,目前使用的版本是 V3 版本的xxx系统平台,简称 V3系统,升级大版本 V4, 前端技术架构也对应做了调整。

V3系统前端使用的是 Angular1.5 ,前后端不分离模式,后端是 .net。V4 要升级成前后端分离模式,前端使用 Vue2 结合 ElementUI 库,目前 Vue2 ElementUI 技术栈相关的使用在公司内部项目里用的都是这个。

关于 ElementUI 组件按需封装, 由于业务需要,这次的升级前端架构设计需要后期支持前端库动态切换,例如动态切换成 Ant Design,代码开发实现使用 ElementUI, 这时前端架构层就需要对 ElementUI 库的所有组件进行封装,然后业务层调用封装好的对应的组件库,组件库里面封装的 ElementUI 组件,或者是 Ant Design 组件。

规范定义

由于需要把ElementUI所有的组件全部封装,而且时间有限,我们组三个前端都需要参与,在实际封装过程中,如果不预先定义对应的规范,不同人的组件命名,变量命名,封装规范等会出现不一样的情况,这时候需要前端小组内部及时统一相关规范,并输出对应的文档。

开始按需封装

我们用脚手架创建了一个 Vue2 的项目,定义好封装目录,把封装的UI组件全部放到 src/components 下面,然后在 App.vue 中引入,进行基本的功能测试。封装需要使用 attrs listeners <slot> 等 Vue.js API 的功能

$attrs

$attrs 用来绑定父组件传到子组件的属性,如 size value

包含了父作用域中不作为 prop 被识别 (且获取) 的 attribute 绑定 (classstyle 除外)。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 (classstyle 除外),并且可以通过 v-bind="$attrs" 传入内部组件——在创建高级别的组件时非常有用。

https://cn.vuejs.org/v2/api/#vm-attrs

$listeners

$listeners 用来绑定父组件传到子组件的事件,如 click change

包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on="$listeners" 传入内部组件——在创建更高层次的组件时非常有用。

https://cn.vuejs.org/v2/api/#vm-listeners

slot

有些组件有自定义功能的实现,业务封装时需要用到,如 input 输入框 复合型输入框

Vue 实现了一套内容分发的 API,这套 API 的设计灵感源自 Web Components 规范草案,将 <slot> 元素作为承载分发内容的出口。

https://cn.vuejs.org/v2/guide/components.html#通过插槽分发内容

https://cn.vuejs.org/v2/guide/components-slots.html

https://cn.vuejs.org/v2/api/#v-slot

Button 按钮 封装

方案一

封装的Button组件, 使用 attrs 接收父组件(应用层)传递的属性参数,使用 listeners 接收父组件(应用层)传递的事件,Button 按钮封装时实际用不上

代码语言:javascript复制
<template>

  <div>

    <el-button

      v-bind="$attrs"

      v-on="$listeners">

        {{ buttonContent }}

    </el-button>

  </div>

</template>



<script>

export default {

  name: 'Button',

  props: {

    buttonContent: {

      type: String,

      default: '按钮'

    }

  }

}

</script>

应用层调用

代码语言:javascript复制

<template>

  <div id="app">

    <button

      type="success"

      size="mini"

      buttonContent="按钮2"

      @click="buttonClick">

    </button>

  </div>

</template>



<script>

import Button from './components/Button.vue';


export default {

  name: 'App',

  components: {

    Button

  },

  methods: {

    buttonClick() => {

      console.log('button click')

    }

  }

}

</script>

方案一优势

封装的组件代码更简洁,业务组件调用时按需传递对应的参数即可实现相应的功能

方案二

封装的Button组件, 使用 props 接收参数对象, <slot> 显示Button按钮文字

代码语言:javascript复制
<template>

  <div>

    <el-button

      :size="buttonConfig.size"

      :type="buttonConfig.type"

      :plain="buttonConfig.plain"

      :round="buttonConfig.round"

      :circle="buttonConfig.circle"

      :loading="buttonConfig.loading"

      :disabled="buttonConfig.disabled"

      :icon="buttonConfig.icon"

      :autofocus="buttonConfig.autofocus"

      :native-type="buttonConfig.nativeType">

      <slot></slot>

    </el-button>

  </div>

</template>


<script>

export default {

  name: 'Button',

  props: {

    buttonConfig: {

      type: Object,

      default: () => {}

    }

  }

}

</script>

应用层调用

代码语言:javascript复制
<template>

  <div id="app">

    <button

      :buttonConfig="button.buttonConfig">

      {{ button.buttonContent }}

    <button>

  </div>

</template>

<script>

import Button from './components/Button.vue';

export default {

  name: 'App',

  components: {

    Button,

  },

  data() {

    return {

      button: {

        buttonContent: '测试按钮1',

        buttonConfig: {

          size: 'small',

          type: 'success',

          icon: 'el-icon-search'

        }

      }

    }

  }

}

</script>
方案二优势

业务层的调用代码更简洁,直接传递一个对象即可,参数定义更灵活,这种方式还支持后期更换UI库,业务层代码不用动,直接更新组件封装层即可。

思考

Button 按钮这种组件封装相对简单一点,在实际业务中,有些组件会比较复杂,例如表格组件的封装使用,各种自定义能力需要支持,对于表格的自定义修改封装后期需要处理的内容会很多,可能也会面临一些取舍,目前小组内还没做到那里,后期会把表格的封装单独梳理出来。

0 人点赞