对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作为自定义组件时,会报很多错误,一点点的改就好啦。

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

相关推荐
用户47949283569151 分钟前
面试官:为什么很多格式化工具都会在行尾额外空出一行
前端
知识分享小能手2 分钟前
Vue3 学习教程,从入门到精通,Vue3 中使用 Axios 进行 Ajax 请求的语法知识点与案例代码(23)
前端·javascript·vue.js·学习·ajax·vue·vue3
一大树2 分钟前
首屏白屏的处理方案~嗖得一下
前端
小old弟4 分钟前
🤔同时发送100个请求?!手撕,并发请求⌨️
前端
533_8 分钟前
[echarts] 更新数据
前端·javascript·echarts
excel9 分钟前
理解 JavaScript 中的迭代器协议与中断行为:for...of vs for...in
前端
幻雨様11 分钟前
UE5多人MOBA+GAS 番外篇:同时造成多种类型伤害,以各种属性值的百分比来应用伤害(版本二)
java·前端·ue5
讨厌吃蛋黄酥15 分钟前
利用Mock实现前后端联调的解决方案
前端·javascript·后端
zzywxc78737 分钟前
在处理大数据列表渲染时,React 虚拟列表是提升性能的关键技术,但在实际实现中常遇到渲染抖动和滚动定位偏移等问题。
前端·javascript·人工智能·深度学习·react.js·重构·ecmascript
Hello.Reader1 小时前
Rust → WebAssembly 的性能剖析全指南
前端·rust·wasm