VUE+CSS模拟组件库的Input组件

154 阅读1分钟

VUE+CSS模拟组件库的Input组件

话不多说,不会插图,样式可能存在不科学的地方,关键是核心利用了CSS变量和表单元素的

:invalid无效伪类和required伪类模拟组件库的input框,直接上代码,欢迎提出宝贵意见

1.html部分:

<template>
    <!-- html结构,必须使用form表单元素才可以和input表单元素的伪类进行联动控制子元素 -->
    <form class="box">
        <!--  -->
        <template v-if="props.label !== ''">
            <label class="label" for="current">
                <span class="star" v-show="props.required">*</span>{{ props.label }}:</label>
        </template>
        <div class="inpbox">
            <!-- 手动双向绑定 input事件-->
            <input :type="props.type" :value="inpVal" @input="changeHandler" 					            		:required="props.required" id="current"
                :placeholder="props.placeholder" />
        </div>
    </form>
</template>

2.js部分,因为应用了CSS的新属性,js大大减少

<script lang="ts" setup>
import { ref } from 'vue';
//存储
const inpVal = ref<string>('')
// 默认接收一个onchange事件,用来向外传递表单元素输入的内容
const emit = defineEmits<{ (e: 'onchange', val: string): void }>()
// 这里配置组件的属性以及默认值
const props = defineProps({
    // placeholder的内容
    placeholder: {
        type: String,
        default: '请输入内容'
    },
    // 输入框前面的文字
    label: {
        type: String,
        default: '用户名'
    },
    // 是否必填
    required: {
        type: Boolean,
        default: false
    },
    // 其实这里应该进一步限定type不应该是radio button checkbox等值
    type: {
        type: String,
        default: 'text'
    }
})
//向外传递数据的回调函数 
const changeHandler = (event: Event) => {
    inpVal.value = (event.target as HTMLInputElement).value
    emit('onchange', inpVal.value)
}

</script>

3.CSS部分,合理运用CSS减少js代码

<style scoped>
/*  
    ·合理利用CSS变量,实现用户按需定制

    ·合理利用:invalid伪类,:required伪类模拟组件库表单input输入框
    可以减少大量js代码,这也是组件库们积极拥抱CSS3的重要原因

    1.单个input输入框依据是否必须 (input 标签上添加required 表示此项必填 )
        对应地我们可以在CSS样式表里进行相应提示,比如当input为必填时,没有输入内容
        我们可以设置边框红色,设置input前面的提示文字红色

    2.单个元素输入内容无效时(input自带email,url等新增的type,自带校验),我们可以
        通过元素的:invalid伪类选择器对样式进行修改

    3.重点:当一个具体表单元素(这里是input)无效或者必须时,想要联动实现该元素
        之外的元素效果时,请保证这些元素都被一个公共的form表单元素包裹,
        这样就可以设置form:invalid .inpbox::after{display:block}
        这段样式表示当input内容无效时就是form无效,form里的.inpbox的伪元素
        将在页面显示
*/
.box {
    /* 输入框内容无效时的边框颜色变量 */
    --inp-required-invalid-border-color: orangered;
    /* 无效内容时的字体颜色 */
    --inp-required-invalid-color: orangered;
    /* 整个组件的宽度 */
    --inp-box-width: 200px;
    /* 组件的高度 */
    --inp-box-height: 70px;
    /* 输入框的宽度 */
    --inp-width: 100px;
    /* 输入框的高度 */
    --inp-height: 15px;
    /* input的圆角,按需传入 */
    --inp-border-radius: 3px;
    /* placeholder的字体颜色 */
    --inp-placeholder-color: deeppink;
    width: var(--inp-box-width);
    height: var(--inp-box-height);
    display: flex;
    justify-content: center;
    align-items: center;
    font-size: calc(var(--inp-box-width) * .06);
}

/* input img这种单标签元素不能添加伪元素,因此我们给input套个盒子并定位 */
.inpbox {
    margin: 0 calc(var(--inp-width) * .1);
    position: relative;
}

/* input 外层盒子的伪元素默认隐藏状态,当内用格式不正确 */
.inpbox::after {
    position: absolute;
    left: 20%;
    top: 100%;
    content: '格式错误';
    color: var(--inp-required-invalid-color);
    display: none;
}

/* 当.box外层的form,注意一定要用form才能和invalid required伪类选择器联动实现效果 */
.box:invalid .inpbox::after {
    display: block;
}

/* input框的宽度高度,这些样式可能不太科学 */
#current {
    width: var(--inp-width);
    height: var(--inp-height);
    border: 1px solid #ccc;
    outline: none;
    border-radius: var(--inp-border-radius);
    font-size: calc(var(--inp-box-width) * .06);
}

#current::placeholder{
    color:var(--inp-placeholder-color);
    font-size: 12px;
    line-height: var(--inp-height);
}

/* 输入框内容无效时的边框颜色和字体颜色 */
#current:invalid {
    border-color: var(--inp-required-invalid-border-color);
    color: var(--inp-required-invalid-color);
}

/* 当输入框无效时label里的字体颜色 */
.box:invalid label[for=current] {
    color: var(--inp-required-invalid-color)
}
/* 让label标签内的元素躺平 */
.label {
    display: flex;
}
</style>

注释写的比较多,有兴趣可以研究研究,CSS3的新特性之多和强大都是不言而喻的,今天就到这里,欢迎点赞,评论,转发,好的作品离不开大家的捧场支持!