element-plus 提供了非常多通用的组件,但要满足特定产品需求效果还是略有差异,所以需再次封装。
概要内容
- 怎么封装成子组件?
- 怎么使用封装组件?
效果对比
-
原始效果
-
封装后效果
怎么封装成子组件?
<template>
<div class="contain">
<el-input
class="input"
:class="{ 'red-border': tips.length > 0 }"
v-model="value"
@input="onInput"
@change="$emit('onChange')"
:placeholder="placeholder"
>
<template #prefix>
<i :class="['iconfont', iconName]"></i>
</template>
</el-input>
<div class="tips" v-if="tips.length > 0">
{{ tips }}
</div>
</div>
</template>
<script>
import { defineComponent, reactive, ref, watch, toRefs } from "vue";
import { ElInput } from "element-plus";
export default defineComponent({
name: "CustomInput",
components: { ElInput },
props: {
modelValue: {
type: [String, Number],
default: "",
},
placeholder: { type: String, default: "" },
oninput: { type: String, default: "" },
iconName: { type: String, default: "" },
tips: { type: String, default: "" },
},
emits: ["input", "update:modelValue", "onChange"],
setup(props, context) {
// 绑定控件的值
const value = ref("");
// 监听属性,给 value 赋值
watch(
() => props.modelValue,
(v1, v2) => {
value.value = v1;
}
);
return {
value,
props,
};
},
methods: {
getIconName() {
return "iconfont " + this.iconName;
},
/** 向父组件提交事件更新数据 */
onInput(e) {
this.$emit("update:modelValue", e);
this.$emit("input", e);
},
},
});
</script>
<style lang="scss">
.input {
height: 50px;
text-align: left;
.iconfont {
font-size: 22px;
color: #127ffc;
display: inline-block;
margin-right: 14px;
}
}
.red-border .el-input__inner {
border: 1px solid #ff6666;
}
.tips {
font-size: 14px;
color: #ff6666;
text-align: left;
margin: 5px auto 20px;
}
</style>
怎么使用封装组件?
-
引入
import CustomInput from "/@/components/CustomInput/index.vue"; export default defineComponent({ components: { CustomInput }, ... }); -
使用
<template> ... <CustomInput class="input-tel" v-model="tel" placeholder="请输入手机号码" iconName="iconshoujihaoma" oninput="`(value = value.replace(/[^\d]/g, ''))`" :tips="telTips" @onChange="telTips = ''" > </CustomInput> ... </template>
总结
- 子组件需watch值变化,然后通过emit 事件上抛值,否则子组件value值变化,上层组件还是原来的值
- 更改子组件默认样式,需要将style 标签中的scoped 去掉,否则会导致怎么也无法覆盖子组件样式情况
参考文献
- Vue 3 - v-model and Components
- Vue3组件(三)把别人的组件拿过来再封装一下
- How to override scoped styles in Vue components?
以上: 如发现有问题,欢迎留言指出,我及时更正