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

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

相关推荐
众生回避几秒前
鸿蒙ms参考
前端·javascript·vue.js
洛千陨1 分钟前
Vue + element-ui实现动态表单项以及动态校验规则
前端·vue.js
GHUIJS1 小时前
【vue3】vue3.5
前端·javascript·vue.js
&白帝&1 小时前
uniapp中使用picker-view选择时间
前端·uni-app
魔术师卡颂1 小时前
如何让“学源码”变得轻松、有意义
前端·面试·源码
谢尔登1 小时前
Babel
前端·react.js·node.js
ling1s1 小时前
C#基础(13)结构体
前端·c#
卸任2 小时前
使用高阶组件封装路由拦截逻辑
前端·react.js
Estrella162 小时前
经典 web 页面排版:三栏布局
前端·css·面试
lxcw2 小时前
npm ERR! code CERT_HAS_EXPIRED npm ERR! errno CERT_HAS_EXPIRED
前端·npm·node.js