对element-plus的组件二次修改-自定义组件

背景

本文是将element-plus的组件提取出来作为业务使用的自定义组件,以transfer组件为例子。

对于element-ui的改造,可以看这篇

正常我们使用transfer效果如下:

当我想给每一个option后面添加一些文字,这就属于自定义组件的范畴了,如下图所示

我给transfer传入的数据里没有哇啦啦啦,我是在组件代码里添加的。

实现过程

我使用了element-plus@2.4.2。在一个正常的引入了element-plus组件的项目中,我们使用方式如下,在HelloWorld.vue中使用transfer。

ts 复制代码
<template>
  <div class="greetings">
    <el-transfer v-model="value" :data="data" style="display: block;" />
  </div>
</template>
<script setup lang="ts">
import { ref } from 'vue'

interface Option {
  key: number
  label: string
  disabled: boolean
}

const generateData = () => {
  const data: Option[] = []
  for (let i = 1; i <= 15; i++) {
    data.push({
      key: i,
      label: `Option ${i}`,
      disabled: i % 4 === 0,
    })
  }
  return data
}

const data = ref<Option[]>(generateData())
const value = ref([])
</script>

接下来我们将/node_modules/element-plus/es/components/transfer这个文件夹复制到HelloWorld.vue同级目录下,如下图:

然后在HelloWorld.vue中引入,如下:

ts 复制代码
<template>
  <div class="greetings">
    <customTransfer v-model="value" :data="data" style="display: block;" />
  </div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import customTransfer from './transfer/index.mjs'

interface Option {
  key: number
  label: string
  disabled: boolean
}

const generateData = () => {
  const data: Option[] = []
  for (let i = 1; i <= 15; i++) {
    data.push({
      key: i,
      label: `Option ${i}`,
      disabled: i % 4 === 0,
    })
  }
  return data
}

const data = ref<Option[]>(generateData())
const value = ref([])
</script>

运行项目,会报很多的错误,接下来我不会一个一个讲,直接贴代码修改处

  1. transfer/src/transfer.mjs

原来:

ts 复制代码
import { isNil } from 'lodash-unified';
import '../../../utils/index.mjs';
import '../../../constants/index.mjs';
import { buildProps, definePropType } from '../../../utils/vue/props/runtime.mjs';
import { mutable } from '../../../utils/typescript.mjs';
import { isArray } from '@vue/shared';
import { CHANGE_EVENT, UPDATE_MODEL_EVENT } from '../../../constants/event.mjs';

改为:

ts 复制代码
import { isNil } from 'lodash-unified';
import 'element-plus/es/utils/index.mjs';
import 'element-plus/es/constants/index.mjs';
import { buildProps, definePropType } from 'element-plus/es/utils/vue/props/runtime.mjs';
import { mutable } from 'element-plus/es/utils/typescript.mjs';
import { isArray } from '@vue/shared';
import { CHANGE_EVENT, UPDATE_MODEL_EVENT } from 'element-plus/es/constants/event.mjs';
  1. transfer/index.mjs

原先为:

ts 复制代码
import '../../utils/index.mjs';
import Transfer from './src/transfer2.mjs';
export { LEFT_CHECK_CHANGE_EVENT, RIGHT_CHECK_CHANGE_EVENT, transferCheckedChangeFn, transferEmits, transferProps } from './src/transfer.mjs';
import { withInstall } from '../../utils/vue/install.mjs';

改为:

ts 复制代码
import 'element-plus/es/utils/index.mjs';
import Transfer from './src/transfer2.mjs';
export { LEFT_CHECK_CHANGE_EVENT, RIGHT_CHECK_CHANGE_EVENT, transferCheckedChangeFn, transferEmits, transferProps } from './src/transfer.mjs';
import { withInstall } from 'element-plus/es/utils/vue/install.mjs';
  1. transfer/src/transfer2.mjs

原先为:

ts 复制代码
import { defineComponent, useSlots, reactive, ref, computed, watch, h, openBlock, createElementBlock, normalizeClass, unref, createVNode, withCtx, renderSlot, createElementVNode, toDisplayString, createCommentVNode } from 'vue';
import '../../../utils/index.mjs';
import '../../../hooks/index.mjs';
import { ElButton } from '../../button/index.mjs';
import { ElIcon } from '../../icon/index.mjs';
import '../../form/index.mjs';
import { ArrowLeft, ArrowRight } from '@element-plus/icons-vue';
import { transferProps, transferEmits } from './transfer.mjs';
import './composables/index.mjs';
import TransferPanel from './transfer-panel2.mjs';
import _export_sfc from '../../../_virtual/plugin-vue_export-helper.mjs';
import { useLocale } from '../../../hooks/use-locale/index.mjs';
import { useNamespace } from '../../../hooks/use-namespace/index.mjs';
import { useFormItem } from '../../form/src/hooks/use-form-item.mjs';
import { usePropsAlias } from './composables/use-props-alias.mjs';
import { useComputedData } from './composables/use-computed-data.mjs';
import { useCheckedChange } from './composables/use-checked-change.mjs';
import { useMove } from './composables/use-move.mjs';
import { debugWarn } from '../../../utils/error.mjs';
import { isEmpty, isUndefined } from '../../../utils/types.mjs';

改为:

ts 复制代码
import { defineComponent, useSlots, reactive, ref, computed, watch, h, openBlock, createElementBlock, normalizeClass, unref, createVNode, withCtx, renderSlot, createElementVNode, toDisplayString, createCommentVNode } from 'vue';
import 'element-plus/es/utils/index.mjs';
import 'element-plus/es/hooks/index.mjs';
import { ElButton } from 'element-plus/es/components/button/index.mjs';
import { ElIcon } from 'element-plus/es/components/icon/index.mjs';
import 'element-plus/es/components/form/index.mjs';
import { ArrowLeft, ArrowRight } from '@element-plus/icons-vue';
import { transferProps, transferEmits } from './transfer.mjs';
import './composables/index.mjs';
import TransferPanel from './transfer-panel2.mjs';
import _export_sfc from 'element-plus/es/_virtual/plugin-vue_export-helper.mjs';
import { useLocale } from 'element-plus/es/hooks/use-locale/index.mjs';
import { useNamespace } from 'element-plus/es/hooks/use-namespace/index.mjs';
import { useFormItem } from 'element-plus/es/components/form/src/hooks/use-form-item.mjs';
import { usePropsAlias } from './composables/use-props-alias.mjs';
import { useComputedData } from './composables/use-computed-data.mjs';
import { useCheckedChange } from './composables/use-checked-change.mjs';
import { useMove } from './composables/use-move.mjs';
import { debugWarn } from 'element-plus/es/utils/error.mjs';
import { isEmpty, isUndefined } from 'element-plus/es/utils/types.mjs';
  1. transfer/src/composables/use-move.mjs

原先为:

ts 复制代码
import '../../../../constants/index.mjs';
import { usePropsAlias } from './use-props-alias.mjs';
import { UPDATE_MODEL_EVENT, CHANGE_EVENT } from '../../../../constants/event.mjs';

改为:

ts 复制代码
import 'element-plus/es/constants/index.mjs';
import { usePropsAlias } from './use-props-alias.mjs';
import { UPDATE_MODEL_EVENT, CHANGE_EVENT } from 'element-plus/es/constants/event.mjs';
  1. transfer/src/composables/use-check.mjs

原先为:

ts 复制代码
import { computed, watch } from 'vue';
import '../../../../utils/index.mjs';
import { CHECKED_CHANGE_EVENT } from '../transfer-panel.mjs';
import { usePropsAlias } from './use-props-alias.mjs';
import { isFunction } from '@vue/shared';

改为:

ts 复制代码
import { computed, watch } from 'vue';
import 'element-plus/es/utils/index.mjs';
import { CHECKED_CHANGE_EVENT } from '../transfer-panel.mjs';
import { usePropsAlias } from './use-props-alias.mjs';
import { isFunction } from '@vue/shared';
  1. transfer/src/transfer-panel2.mjs

原先为:

ts 复制代码
import { defineComponent, useSlots, reactive, computed, toRefs, openBlock, createElementBlock, normalizeClass, unref, createElementVNode, createVNode, isRef, withCtx, createTextVNode, toDisplayString, createBlock, createCommentVNode, withDirectives, Fragment, renderList, vShow, renderSlot } from 'vue';
import '../../../utils/index.mjs';
import '../../../hooks/index.mjs';
import { ElCheckbox, ElCheckboxGroup } from '../../checkbox/index.mjs';
import { ElInput } from '../../input/index.mjs';
import { Search } from '@element-plus/icons-vue';
import { transferPanelProps, transferPanelEmits } from './transfer-panel.mjs';
import './composables/index.mjs';
import _export_sfc from '../../../_virtual/plugin-vue_export-helper.mjs';
import { useLocale } from '../../../hooks/use-locale/index.mjs';
import { useNamespace } from '../../../hooks/use-namespace/index.mjs';
import { usePropsAlias } from './composables/use-props-alias.mjs';
import { useCheck } from './composables/use-check.mjs';
import { isEmpty } from '../../../utils/types.mjs';

改为:

ts 复制代码
import { defineComponent, useSlots, reactive, computed, toRefs, openBlock, createElementBlock, normalizeClass, unref, createElementVNode, createVNode, isRef, withCtx, createTextVNode, toDisplayString, createBlock, createCommentVNode, withDirectives, Fragment, renderList, vShow, renderSlot } from 'vue';
import 'element-plus/es/utils/index.mjs';
import 'element-plus/es/hooks/index.mjs';
import { ElCheckbox, ElCheckboxGroup } from 'element-plus/es/components/checkbox/index.mjs';
import { ElInput } from 'element-plus/es/components/input/index.mjs';
import { Search } from '@element-plus/icons-vue';
import { transferPanelProps, transferPanelEmits } from './transfer-panel.mjs';
import './composables/index.mjs';
import _export_sfc from 'element-plus/es/_virtual/plugin-vue_export-helper.mjs';
import { useLocale } from 'element-plus/es/hooks/use-locale/index.mjs';
import { useNamespace } from 'element-plus/es/hooks/use-namespace/index.mjs';
import { usePropsAlias } from './composables/use-props-alias.mjs';
import { useCheck } from './composables/use-check.mjs';
import { isEmpty } from 'element-plus/es/utils/types.mjs';
  1. transfer/src/transfer-panel.mjs

原先为:

ts 复制代码
import '../../../utils/index.mjs';
import { transferProps, transferCheckedChangeFn } from './transfer.mjs';
import { buildProps, definePropType } from '../../../utils/vue/props/runtime.mjs';

改为:

ts 复制代码
import 'element-plus/es/utils/index.mjs';
import { transferProps, transferCheckedChangeFn } from './transfer.mjs';
import { buildProps, definePropType } from 'element-plus/es/utils/vue/props/runtime.mjs';

改到这里,项目启动就不会报错了。

开始魔改

此刻你在transfer的代码里做的修改,都会体现在界面上。

回到一开始的需求,给每个option添加额外的文字,打开transfer/src/transfer2.mjs

将一下代码:

ts 复制代码
const optionRender = computed(() => (option) => {
      if (props.renderContent)
        return props.renderContent(h, option);
      if (slots.default)
        return slots.default({ option });
      return h("span", option[propsAlias.value.label] || option[propsAlias.value.key]);
    });

改为:

ts 复制代码
const optionRender = computed(() => (option) => {
      if (props.renderContent)
        return props.renderContent(h, option);
      if (slots.default)
        return slots.default({ option });
      return h("span", option[propsAlias.value.label] + '哇哈哈哈,我来啦' || option[propsAlias.value.key]);
    });

就有对应的修改啦

总结

其实你在引入transfer作为自定义组件时,会报很多错误,一点点的改就好啦。

看到这里的看官,麻烦点个赞赞哇

相关推荐
y先森38 分钟前
CSS3中的伸缩盒模型(弹性盒子、弹性布局)之伸缩容器、伸缩项目、主轴方向、主轴换行方式、复合属性flex-flow
前端·css·css3
前端Hardy38 分钟前
纯HTML&CSS实现3D旋转地球
前端·javascript·css·3d·html
susu108301891141 分钟前
vue3中父div设置display flex,2个子div重叠
前端·javascript·vue.js
IT女孩儿2 小时前
CSS查缺补漏(补充上一条)
前端·css
吃杠碰小鸡3 小时前
commitlint校验git提交信息
前端
虾球xz3 小时前
游戏引擎学习第20天
前端·学习·游戏引擎
我爱李星璇3 小时前
HTML常用表格与标签
前端·html
疯狂的沙粒3 小时前
如何在Vue项目中应用TypeScript?应该注意那些点?
前端·vue.js·typescript
小镇程序员4 小时前
vue2 src_Todolist全局总线事件版本
前端·javascript·vue.js
野槐4 小时前
前端图像处理(一)
前端