样式

子组件代码
<template>
<div class="special-validate el-form--item" :class="!isValidated ? 'is-error': '' ">
<el-input
v-model="value"
placeholder="Please enter"
:disabled="isDisabled"
@focus="()=>{validateInfo.isShow = true}"
@blur="()=>{validateInfo.isShow = false}"
@input="handleInput(value)"
/>
<div class="validate-meesage" v-if="validateInfo.isShow" :show-message="false">
<div v-for="(item) in validateInfo.info" :key="item.message">
<div class="validate-info-box">
<span class="icon-box"><svg-icon :name="item.icon" style="width: 12px;height: 12px"></svg-icon></span>
<span class="message-box" :class="item.icon==='fail'?'fail-message':''">{{ item.message }}</span>
</div>
</div>
</div>
</div>
</template>
 => [],
required: true
},
isDisabled: {
type: Boolean,
default: false
}
},
setup(props, context) {
let isValidated = ref(true);
const infoList = props.validateInfoList;
const validateInfo = reactive({
isShow: false,
info: []
});
infoList.forEach(item => {
const { message, rule } = item;
validateInfo.info.push({ message, rule, icon: "warning" });
});
const handleInput = (value) => {
context.emit("update:value", value);
let validateRes = false;
validateInfo.info.forEach(validate => {
const rule = validate.rule;
let isValidated = false;
if (Object.prototype.toString.call(rule) === "[object RegExp]") {
isValidated = rule.test(value);
} else if (typeof rule === "function") {
isValidated = rule(value);
}
validate.icon = isValidated ? "success" : "fail";
});
validateRes = validateInfo.info.every(item => item.icon === "success");
isValidated = validateRes;
return validateRes;
};
return {
isValidated,
validateInfo,
handleInput
};
}
});
</script>
<style scoped lang="scss">
.special-validate {
position: relative;
width: 100%;
.validate-meesage {
position: absolute;
left: calc(100% + 10px);
top: 50%;
transform: translateY(-50%);
width: 300px;
background-color: #fff;
box-shadow: 0px 2px 10px 0px rgba(37, 54, 109, 0.12);
border: 1px solid #E9ECF5;
padding: 12px;
padding-bottom: 4px;
border-radius: 8px;
font-size: 11px;
color: #4C4E5A;
&:before {
content: '';
position: absolute;
border-left: 6px solid transparent;
border-top: 6px solid transparent;
border-bottom: 6px solid transparent;
border-right: 6px solid #fff;
left: -12px;
top: 51%;
transform: translateY(-50%);
}
&:after {
content: '';
display: block;
position: absolute;
width: 7px;
height: 7px;
border: 1px solid #E9ECF5;
border-top: none;
border-right: none;
left: -8px;
top: 50%;
transform: rotate(45deg) translateY(-50%);
}
.validate-info-box {
line-height: 16px;
margin-bottom: 8px;
display: flex;
.icon-box {
padding-top: 2px;
margin-right: 8px;
}
.message-box.fail-message {
color: #FC4646;
}
}
}
}
</style>
父组件使用
<el-form-item label="Catalog ID" prop="catalogId" class="required-sign">
<muti-validate-input
v-model:value="obj.catalogId"
:is-disabled="text === 'Edit Catalog'"
:validate-info-list="validateIdInfoList">
</muti-validate-input>
</el-form-item>