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

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

相关推荐
MickeyCV1 小时前
Nginx学习笔记:常用命令&端口占用报错解决&Nginx核心配置文件解读
前端·nginx
祈澈菇凉1 小时前
webpack和grunt以及gulp有什么不同?
前端·webpack·gulp
zy0101011 小时前
HTML列表,表格和表单
前端·html
初辰ge1 小时前
【p-camera-h5】 一款开箱即用的H5相机插件,支持拍照、录像、动态水印与样式高度定制化。
前端·相机
HugeYLH2 小时前
解决npm问题:错误的代理设置
前端·npm·node.js
六个点2 小时前
DNS与获取页面白屏时间
前端·面试·dns
道不尽世间的沧桑2 小时前
第9篇:插槽(Slots)的使用
前端·javascript·vue.js
bin91533 小时前
DeepSeek 助力 Vue 开发:打造丝滑的滑块(Slider)
前端·javascript·vue.js·前端框架·ecmascript·deepseek
uhakadotcom3 小时前
最新发布的Tailwind CSS v4.0提供了什么新能力?
前端
GISer_Jing3 小时前
Node.js中如何修改全局变量的几种方式
前端·javascript·node.js