组件封装与复用全攻略
🎯 引言
掌握组件封装与复用是前端开发中的必备技能。通过封装 Element UI 组件,不仅能减少重复代码,还能统一界面风格,提高项目的可维护性和扩展性。这篇文章将手把手教你如何封装对话框、输入框和选择器组件,让你轻松驾驭 Element UI。
🔧 为什么要封装组件?
在项目开发中,你可能会遇到很多重复使用的组件,比如弹窗、输入框、下拉选择等。每次都写一遍逻辑或者样式不仅浪费时间,还容易出错。封装组件的好处主要表现在:
- 复用逻辑,避免重复造轮子。
- 统一样式,保证整体 UI 风格一致。
- 方便维护,修改一次即可影响所有实例。
- 支持灵活的定制,比如插槽、事件回调让组件更通用。
💬 封装对话框组件
Element UI 的 el-dialog 是非常实用的弹窗组件,封装它能让你快速创建各种弹窗,且支持灵活配置。
1. 定义常用属性
我们通常需要设置弹窗的标题、宽度、底部按钮文字等。这里封装一个基础的对话框组件 MyDialog:
<template>
<el-dialog :title="title" :visible.sync="visible" :width="width" @close="handleClose">
<slot></slot>
<span slot="footer" class="dialog-footer">
<el-button @click="handleCancel">{{ cancelText }}</el-button>
<el-button type="primary" @click="handleConfirm">{{ confirmText }}</el-button>
</span>
</el-dialog>
</template>
<script>
export default {
name: 'MyDialog',
model: {
prop: 'value',
event: 'update:value',
},
props: {
value: {
type: String,
default: '',
},
title: {
type: String,
default: '提示',
},
width: {
type: String,
default: '50%',
},
confirmText: {
type: String,
default: '确定',
},
cancelText: {
type: String,
default: '取消',
},
},
computed: {
visible: {
get() {
return this.value;
},
set(val) {
this.$emit('update:value', val);
},
},
},
methods: {
handleConfirm() {
this.$emit('confirm');
},
handleCancel() {
this.$emit('cancel');
this.$emit('update:value', false);
},
handleClose() {
this.$emit('close');
},
},
};
</script>
2. 使用示例
<template>
<div>
<el-button @click="showDialog = true">打开对话框</el-button>
<my-dialog
v-model="showDialog"
title="自定义标题"
width="60%"
confirmText="确定"
cancelText="关闭"
@confirm="onConfirm"
@cancel="onCancel"
>
<p>这是对话框内容,可以放任何内容。</p>
</my-dialog>
</div>
</template>
<script>
import MyDialog from './MyDialog.vue';
export default {
components: { MyDialog },
data() {
return {
showDialog: false,
};
},
methods: {
onConfirm() {
this.$message.success('点击了确定!');
this.showDialog = false;
},
onCancel() {
this.$message.info('点击了取消!');
},
},
};
</script>
prop 和事件暴露控制权限,避免直接操作内部状态,这样更灵活也更安全。📝 封装输入框组件
输入框是表单中最常用的元素。Element UI 的 el-input 支持丰富的属性和事件,封装时可以加入校验、长度限制以及统一样式。
1. 基础封装
创建一个 MyInput 组件:
<template>
<el-form-item :label="label" :prop="prop" :rules="rules">
<el-input
v-model="innerValue"
:placeholder="placeholder"
:maxlength="maxlength"
show-word-limit
/>
</el-form-item>
</template>
<script>
export default {
name: 'MyInput',
model: {
prop: 'value',
event: 'update:value',
},
props: {
value: {
type: String,
default: '',
},
label: {
type: String,
default: '',
},
placeholder: {
type: String,
default: '请输入内容',
},
prop: {
type: String,
default: '',
},
rules: {
type: Array,
default: () => [],
},
maxlength: {
type: Number,
default: 50,
},
},
computed: {
innerValue: {
get() {
return this.value;
},
set(val) {
this.$emit('update:value', val);
},
},
},
};
</script>
<style scoped>
.el-input {
width: 100%;
}
</style>
2. 使用示例
<template>
<el-form :model="form" :rules="rules" ref="formRef">
<my-input
v-model="form.username"
label="用户名"
prop="username"
:rules="rules.username"
:maxlength="20"
/>
<el-button type="primary" @click="submitForm">提交</el-button>
</el-form>
</template>
<script>
import MyInput from './MyInput.vue';
export default {
components: { MyInput },
data() {
return {
form: {
username: '',
},
rules: {
username: [
{
required: true,
message: '请输入用户名',
trigger: 'blur',
},
{
min: 3,
max: 20,
message: '长度在 3 到 20 个字符',
trigger: 'blur',
},
],
},
};
},
methods: {
submitForm() {
this.$refs.formRef.validate(valid => {
if (valid) {
this.$message.success('提交成功!');
}
});
},
},
};
</script>
el-form-item 的 prop 与规则对应,封装输入框后,配合 Element UI 的表单验证机制能大大提升开发效率。🎯 封装选择器组件
选择器组件在业务场景中非常常见,比如下拉菜单、多选框等。Element UI 提供了丰富的选择器组件,我们这里以封装一个基础的单选下拉选择器为例。
1. 基础封装
封装一个 MySelect 组件
<template>
<el-form-item :label="label" :prop="prop" :rules="rules">
<el-select v-model="innerValue" :placeholder="placeholder" @change="onChange">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</template>
<script>
export default {
name: 'MySelect',
model: {
prop: 'value',
event: 'update:value',
},
props: {
value: {
required: true,
},
label: {
type: String,
default: '',
},
prop: {
type: String,
default: '',
},
rules: {
type: Array,
default: () => [],
},
placeholder: {
type: String,
default: '请选择',
},
options: {
type: Array,
default: () => [],
},
},
computed: {
innerValue: {
get() {
return this.value;
},
set(val) {
this.$emit('update:value', val);
},
},
},
methods: {
onChange(val) {
this.$emit('input', val);
this.$emit('change', val);
},
},
};
</script>
<style scoped>
.el-select {
width: 100%;
}
</style>
2. 使用示例
<template>
<el-form :model="form" :rules="rules" ref="formRef">
<my-select
v-model="form.gender"
label="性别"
prop="gender"
:options="genderOptions"
:rules="rules.gender"
/>
<el-button type="primary" @click="submitForm">提交</el-button>
</el-form>
</template>
<script>
import MySelect from './MySelect.vue';
export default {
components: { MySelect },
data() {
return {
form: {
gender: '',
},
genderOptions: [
{ label: '男', value: 'male' },
{ label: '女', value: 'female' },
],
rules: {
gender: [
{
required: true,
message: '请选择性别',
trigger: 'change',
},
],
},
};
},
methods: {
submitForm() {
this.$refs.formRef.validate(valid => {
if (valid) {
this.$message.success('提交成功!');
}
});
},
},
};
</script>
options 传递选择项,保持组件通用性;事件 change 也要支持,方便业务调用。🧾 小节总结
- 组件封装能有效减少重复代码,实现样式和逻辑的统一,提高项目整体质量。
- 对话框组件封装时要支持插槽、自定义回调,满足不同业务需求。
- 输入框和选择器组件的封装,结合 Element UI 的表单验证规则,提高表单开发效率和体验。
❓ 知识问答(Q&A)
Q:为什么要用 .sync 修饰符绑定对话框的 visible 属性?
A:.sync 修饰符用于实现父组件和子组件之间的双向绑定。当对话框内调用 update:visible 事件时,父组件的 visible 状态也会同步更新,实现显示与隐藏的同步控制。
Q:封装输入框时,如何实现统一的校验规则?
A:可以通过 el-form 和 el-form-item 的 rules 属性传入统一的验证规则,输入框组件只需将 prop 和 rules 作为参数传递,结合 Element UI 的校验机制即可。
🧪 小练习
练习1
在封装对话框基础上,添加一个自定义底部按钮,按钮文字和事件由父组件传入。
<template>
<my-dialog :visible.sync="visible" title="多按钮对话框" @confirm="onConfirm" @cancel="onCancel">
<p>内容区域</p>
<template v-slot:footer>
<!-- 自定义按钮区域 -->
</template>
</my-dialog>
</template>
<script>
export default {
data() {
return { visible: false };
},
methods: {
onConfirm() {
/* 处理确认 */
},
onCancel() {
/* 处理取消 */
},
},
};
</script>
练习2
封装一个多选下拉组件,支持传入多选选项,返回选中的数组。
<template>
<el-select v-model="innerValue" multiple :placeholder="placeholder" @change="onChange">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</template>
<script>
export default {
props: {
/* ... */
},
data() {
/* ... */
},
methods: {
/* ... */
},
};
</script>
🎉 恭喜你已经掌握 Element UI 组件封装、插槽使用、表单校验这几项技能啦!
