在组件库中封装element-plus - 自己撸组件库篇三

大家好,我是鸽鸽。

前面我们一起从零开始搭建了一个公共组件库,在公司有资源维护的情况下,造轮子无疑是自我提升和刷kpi的好方法。但实际上,封装第三方组件库并添加公司的业务逻辑基本上就够用了。

本篇文章我们在之前的组件库的基础上,封装element-plus的el-input组件,一起了解二次封装的要点和技巧。

相关代码在这 learn-create-compoents-lib/class3,建议搭配食用

系列文章
《搭建vue3 & ts组件库脚手架 - 自己撸组件库篇一》
《组件库版本的管理和发布 - 自己撸组件库篇二》
《在组件库中封装element-plus - 自己撸组件库篇三》

安装element-plus

正常情况下,我们的项目中会安装有自己的element-plus版本。如果再将element-plus安装到组件库的话,那么项目安装依赖时会下载多个element-plus的版本。

实际上我们希望的是组件库能够使用项目的element-plus版本即可。

在这种情况下可以使用package.jsonpeerDependencies来声明外部依赖。

我们在组件库的 package.json 里添加声明

json 复制代码
// /packages/components/package.json
{
  "peerDependencies": {
    "element-plus": "^2.3.9"
  }
}

然后我们在测试项目也就是根目录的package.json文件中安装element-plus

json 复制代码
// /package.json
{
  "dependencies": {
    "@giegie/components": "workspace:*",
    "vue": "^3.3.4",
    "element-plus": "^2.3.9"
  }
}

配置都写好后,使用 pnpm install 进行安装

修改项目打包配置

排除打包依赖

在之前的文章中,我们在打包时排除了vue依赖。这里也一样,我们要排除element-plus有关的依赖,在组件库的vite.config.ts中进行修改

typescript 复制代码
// /packages/components/vite.config.ts
export default defineConfig(() => {
  return {
    external: ['vue', 'element-plus', '@element-plus/icons-vue', /\.scss/]
  }
})

其中@element-plus/icons-vueelement-plus图标相关的依赖

排除掉 scss是因为我们要在组件中引入element-plus的样式,但是这个样式也要从外部项目的element-plus依赖中获取

为什么是scss而不是css呢? 因为在项目内通常会定制化element-plus的样式,这都是通过修改element-plus的scss变量来完成的。如果想定制的样式能影响封装在我们组件库中element-plus组件的话,后面在我们的组件也必须要引入element-plus的scss样式。

自动引入element-plus的样式

在编写我们组件库的组件时,需要使用按需加载的方式引入element-plus组件,如:

html 复制代码
<template>
  <el-input  />
</template>
<script setup lang="ts">
import { ElInput } from 'element-plus'
import 'element-plus/theme-chalk/src/base.scss'
import 'element-plus/theme-chalk/src/input.scss'
</script>

可以看到我们不仅要引入组件,还需要引入基础样式和组件样式,这个需要的element-plus组件变多的话,非常麻烦。

我们需要使用unplugin-element-plus帮助我们自动引入样式

安装unplugin-element-plus 到组件库的包下

bash 复制代码
pnpm add unplugin-element-plus -D --filter components

vite配置文件里添加下面配置

typescript 复制代码
// /packages/components/vite.config.ts
import ElementPlus from 'unplugin-element-plus/vite'
export default defineConfig(() => {
  return {
    plugins: [
      // ...
      ElementPlus({
        // 导入scss而不是css
        useSource: true
      }),
    ]
  }
})

配置好后,编写组件时只用向下面这样就行

html 复制代码
<template>
  <el-input  />
</template>
<script setup lang="ts">
import { ElInput } from 'element-plus'
</script>

简单封装el-input组件

将之前封装好的gie-input中的input换成el-input组件,功能和之前一样,最终文件如下

html 复制代码
<template>
  <div class="gie-input">
    <el-input v-model="state" ref="inputRef" type="text" :disabled="props.disabled" />
  </div>
</template>
<script setup lang="ts">
import { computed, ref } from 'vue'
import { ElInput } from 'element-plus'
import type { InputEmits, InputProps } from './Input';

defineOptions({
  name: 'GieInput',
})

const emit = defineEmits<InputEmits>()

const props = withDefaults(defineProps<InputProps>(), {
  modelValue: '',
  disabled: false
})

const state = computed({
  get: () => props.modelValue,
  set: (val) => {
    emit('update:modelValue', val)
  }
})

const inputRef = ref<InstanceType<typeof ElInput>>()

function focus() {
  inputRef.value?.focus()
}

defineExpose({
  focus
})
</script>

运行打包和预览命令

bash 复制代码
npm run build
npm run dev

在浏览器中可以看到结果

将组件接入到el-form的表单校验

我们在组件库里封装的组件,大概分为3类。表单组件、数据展示组件和布局组件。

其中表单组件一般都会和element-plus里的el-form组件结合使用。假如我们自己封装一个富文本组件,当输入后失去焦点且字段要求必填时,会自动触发el-form的校验。此时需要显示错误提示和我们自己封装的富文本的边框变红,这应该如何实现呢?

首先我们需要在组件里获取到el-form-item组件的实例,element-plus暴露了一个contextKey,可以让我们方便的将el-form-item实例注入进来:

html 复制代码
<script setup lang="ts">
import { formItemContextKey } from 'element-plus'
const elFormItem = inject(formItemContextKey)
</script>

然后通过元素的blur事件调用校验方法:

html 复制代码
<template>
  <div contenteditable="true" @blur="onBlur"></div>
</template>
<script setup lang="ts">
import { formItemContextKey } from 'element-plus'
const elFormItem = inject(formItemContextKey)

const onBlur = () => {
  elFormItem!.validate?.('blur').catch((err) => console.warn(err))
}
</script>

可以看到上面validate方法的参数为blur,这个表示执行项目中规则的triggerblur的校验。

typescript 复制代码
const rules = reactive<FormRules<RuleForm>>({
  test: [
    { required: true, message: '请输入文字', trigger: 'blur' },
  ]
})

到这里错误提示可以在失去焦点并校验失败时自动显示出来,下面开始修改错误时的边框样式。

可以看到,当校验失败时,el-form-item上会加上is-errorclass,我们只用通过class来修改边框即可

scss 复制代码
.gie-richtext{
  flex: 1;
  &__control{
    border: 1px solid #aaa;
    background: #eee;
    border-radius: 5px;
    padding: 16px;
    min-height: 100px;
    .is-error & {
      border-color: red;
    }
  }
}

总结

本篇文章学习了通过peerDependencies安装element-plus,并在打包时将element-plus相关的包排除在外。封装element-plus,以及和el-form校验相结合。

到这里基本上组件库封装element-plus就完成了,以后再复杂的组件也只需要在这套脚手架项目上添砖加瓦即可。

以后有好的组件库编写技巧的话会继续分享的咕!

相关推荐
开心工作室_kaic3 小时前
ssm111基于MVC的舞蹈网站的设计与实现+vue(论文+源码)_kaic
前端·vue.js·mvc
bug爱好者3 小时前
如何解决sourcetree 一打开就闪退问题
前端·javascript·vue.js
迂 幵4 小时前
vue el-table 超出隐藏移入弹窗显示
javascript·vue.js·elementui
上趣工作室4 小时前
vue2在el-dialog打开的时候使该el-dialog中的某个输入框获得焦点方法总结
前端·javascript·vue.js
家里有只小肥猫4 小时前
el-tree 父节点隐藏
前端·javascript·vue.js
_xaboy5 小时前
开源项目低代码表单设计器FcDesigner扩展自定义的容器组件.例如col
vue.js·低代码·开源·动态表单·formcreate·低代码表单·可视化表单设计器
_xaboy5 小时前
开源项目低代码表单设计器FcDesigner扩展自定义组件
vue.js·低代码·开源·动态表单·formcreate·可视化表单设计器
mez_Blog5 小时前
Vue之插槽(slot)
前端·javascript·vue.js·前端框架·插槽
爱睡D小猪5 小时前
vue文本高亮处理
前端·javascript·vue.js
paopaokaka_luck5 小时前
基于Spring Boot+Vue的多媒体素材管理系统的设计与实现
java·数据库·vue.js·spring boot·后端·算法