starwait/components/Ni/Input.vue
2025-04-27 04:17:35 +08:00

118 lines
3.0 KiB
Vue

<script setup lang="ts">
const props = defineProps({
modelValue: { // v-model 默认接收的属性
type: [String, Number],
default: ''
},
clear: {
type: Boolean,
default: false
},
type: {
// 按钮类型
type: String,
default: 'text',
validator: (value: string) => ['text', 'password'].includes(value)
},
disabled: {
// 禁用
type: Boolean,
default: false,
},
showPasswordOn: {
// 查看密码的事件
type: String,
default: 'click',
validator: (value: string) => ['click', 'mouseDown'].includes(value)
},
})
const emit = defineEmits([
'update:modelValue', // v-model 必须
'focus', // 聚焦事件
'blur' // 失焦事件
])
const inputRef = ref(null)
const clear = ref(props.clear)
const type = ref(props.type)
const disabled = ref(props.disabled)
const showPasswordOn = ref(props.showPasswordOn)
watchEffect(() => {
clear.value = props.clear;
type.value = props.type;
disabled.value = props.disabled;
showPasswordOn.value = props.showPasswordOn
})
// 输入事件处理
const handleInput = (event) => {
emit('update:modelValue', event.target.value)
}
// 聚焦事件透传
const handleFocus = (event) => {
emit('focus', event)
}
// 失焦事件透传
const handleBlur = (event) => {
emit('blur', event)
}
// 暴露方法(可选)
defineExpose({
focus: () => inputRef.value.focus(),
blur: () => inputRef.value.blur()
})
</script>
<template>
<div class="NiInput" data-prefix="Ni">
<div class="before">
<slot name="before"></slot>
</div>
<div class="inputMain">
<!-- 透传所有原生属性 v-bind="$attrs" -->
<input type="text" ref="inputRef"
class="ni-input"
:value="modelValue"
v-bind="$attrs"
@input="handleInput"
@focus="handleFocus"
@blur="handleBlur"></div>
<div class="show-password"></div>
<div class="after">
<slot name="after"></slot>
</div>
</div>
</template>
<style scoped lang="scss">
.NiInput {
position: relative;
height: 100%;
& > div.inputMain {
position: relative;
width: 100%;
height: 100%;
display: flex;
align-items: center;
& > input {
height: 2rem;
width: 100%;
outline: none;
border: 1px solid var(--Ni-theme-border-color);
padding: .2rem .5rem;
border-radius: var(--Ni-border-radius);
box-sizing: border-box;
transition: border 0.3s ease-in-out;
font-size: 1rem;
font-family: v-sans, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
&:hover {
border-color: var(--Ni-theme-border-color-hover);
}
}
}
}
</style>