使用vue3以及原生input实现一个可复用的组件(包括各种数组类型,手机号类型,小数类型)

看标题要实现可复用 那我就注册到全局组件里面 在component.ts

javascript 复制代码
//注册全局公共组件
import MxInput from '@/components/common/MxInput.vue' 
const commonComponents = {
    install(Vue) {
        Vue.component('MxInput', MxInput)
    }
};
export default commonComponents;

子组件:

javascript 复制代码
<template>
    <div class="van_input_wrapper">
        <input :type="props.type" :value="props.modelValue" :disabled="props.disabled"  :maxlength="props.maxlength" :placeholder="props.placeholder"  @input="_onInput"  @blur="_onBlur" @click="_click"  :class="{ 'disabled-input': props.disabled, 'error-input': props.error }"   class="van_input" />
        <span  v-if="props.modelValue && !props.disabled" class="input_del" @click="clearInputValue"></span>
    </div>
</template>

<script setup lang="ts">
import { reactive} from 'vue';
// var obj = {
// 1:'下拉列表', 2:'文本', 3:'多行文本', 4:'数字', 5:'小数', 6:'复选框',-->
//  7:"正则表达式", 8:"日期", 9:'短信', 10:'验证码', 11:'表单', 12:'附件',-->
//  13:'评星', 14:'高级复选框', 15:'商品表', 16:'满意度评价表', 17:'文本(电话类型)', 18:'级联',-->
// 19:'地理位置', 20:'资产表', 21:'表单关联', 24:'支付', 23:'签名', 25:'计算字段', 26:'日期时间'-->
// }
interface iObj {
    isDelButtonVisible:boolean
    [key: string]: any
}

//props 定义类型
interface iProps {
    type?:string //input类型
    fieldType?:string //字段类型
    placeholder: string
    maxlength?: string //长度设置
    disabled?: boolean  //disabled
    error?:boolean  //错误样式
    modelValue?: string  //v-model
    [key: string]: any
}
//emit
interface iEmit {
    (e: 'click', value: string): void
    (e: 'input', value: string): void
    (e: 'change', value: string): void
    (e: 'update:modelValue', value: string): void   //更新v-model
}
//vue3中props edit注册
let emit = defineEmits<iEmit>();
let props = withDefaults(defineProps<iProps>(), {
    type:'text'
})

const data:iObj = reactive({
    isDelButtonVisible:false
})
//input事件
function _onInput(event){
    const inputValue = event.target.value;
    const fieldType = props.fieldType;
    const inputElement = event.target;
    console.log(11212,event.target.value,props.fieldType)
    if(fieldType === '5'){
        // 限制小数点后两位
        const pattern = /^-?([1-9]\d*|0)(\.\d+)?$/;
        if (!pattern.test(inputValue)) {
            // 如果不符合格式,则调整输入值
            const parts = inputValue.split('.');
            if (parts.length > 1 && parts[1].length > 2) {
                // 如果小数点后超过两位,则截断
                event.target.value = `${parts[0]}.${parts[1].substring(0, 2)}`;
            }
        }
    }else if(fieldType === '4'){
        //只能输入数字
        inputElement.value = '';
        event.target.value = inputValue.replace(/[^\d]/g, '')
    }
    console.log(22212,event.target.value)
    emit('update:modelValue',event.target.value)
    emit('input',event)
}
//失去焦点
function _onBlur(event) {
    const inputValue = event.target.value;
    const fieldType = props.fieldType;

    if (fieldType === '5') {
        // 检查小数点后是否不足两位
        const parts = inputValue.split('.');
        console.log(parts,parts.length)
        if(inputValue){
            if (parts.length === 2 && parts[1].length === 1) {
                // 如果只有一位小数,则补全为两位
                event.target.value = `${inputValue}0`;
            } else if (parts.length === 1) {
                // 如果没有小数部分,则添加 .00
                event.target.value = `${inputValue}.00`;
            }
        }

        emit('update:modelValue', event.target.value);
    }else if (fieldType === '17') {
        // 手机号正则表达式
        const phonePattern = /^1[3-9]\d{9}$/;
        if (!phonePattern.test(inputValue)) {
            // 如果不是有效的手机号,可以显示错误提示或者进行其他处理
            console.error('请输入有效的手机号');
            // 这里可以添加更多的逻辑,比如显示错误消息或者修改样式等
        }else{
            emit('update:modelValue', inputValue);
        }
    }
}

function _click(event){
    emit('click',event)
}
function clearInputValue() {
    emit('update:modelValue','')
}
</script>

<style scoped lang="less">
.van_input_wrapper{
    position: relative;
}
.van_input{
    width: calc(100% - 38px);
    height: 40px;
    border-radius: 5px;
    border: 1px solid #DDE0E8;
    color:rgba(0,0,0,0.9);
    font-weight: 400;
    font-size: 14px;
    line-height: 42px;
    padding:0 30px 0 8px;
}
.disabled-input{
    background: #F0F2F4;
    border-radius: 4px;
    border: 1px solid #DDE0E8;
}
.error-input{
    box-shadow: 0px 0px 4px 0px rgba(244,78,78,0.5);
    border-radius: 4px;
    border: 1px solid #F44E4E;
}
.input_del{
    display: block;
    position: absolute;
    right: 10px;
    top:14px;
    width: 14px;
    height: 14px;
    background: url("./src/assets/img/input_del.png") no-repeat center center;
    background-size: 14px 14px;
}
.van_input:focus{
    border: 1px solid #0162E2;
    box-shadow: 0 0 4px 0 rgba(1,98,226,0.5);
}
.van_input::-webkit-input-placeholder{
    color:rgba(0,0,0,0.35);
    font-weight: 400;
    font-size: 14px;
}
.van_input:-moz-placeholder, textarea:-moz-placeholder {
    color:rgba(0,0,0,0.35);
    font-weight: 400;
    font-size: 14px;
}
.van_input::-moz-placeholder, textarea::-moz-placeholder {
    color:rgba(0,0,0,0.35);
    font-weight: 400;
    font-size: 14px;
}
.van_input:-ms-input-placeholder, textarea:-ms-input-placeholder {
    color:rgba(0,0,0,0.35);
    font-weight: 400;
    font-size: 14px;
}
</style>
相关推荐
wuxia211812 小时前
微信小程序单击元素切换元素的显示和隐藏
javascript·微信小程序·setdata
JustHappy12 小时前
古法编程秘籍(二):什么是代码模块化?别背概念,把房间收拾明白就够了
前端·后端
小江的记录本12 小时前
【JVM虚拟机】堆内存分代模型:年轻代(Eden+Survivor)、老年代、元空间Metaspace(附《思维导图》+《面试高频考点清单》)
java·前端·jvm·后端·python·spring·面试
weixin_4713830312 小时前
图片预解码缓存
前端·浏览器缓存·图片预解码
一起学开源12 小时前
一文读懂 ReAct 范式:让 AI Agent 真正学会“思考+行动“
java·javascript·react.js·ecmascript·react·alibaba·智能体开发
岁月宁静14 小时前
驾驭 AI 这匹野马:深入解析智能体 Harness 工程
vue.js·python
郑洁文14 小时前
基于网络爬虫的Web敏感信息泄露自动化检测工具
前端·爬虫·网络安全·自动化
游九尘14 小时前
JavaScript 实现三段式版本号对比函数(app升级用)
javascript·uni-app
zhiSiBuYu051714 小时前
Claude-Code 新手极速上手指南
javascript·node.js
郑洁文15 小时前
可视化Web渗透分析工具的设计与实现
前端