magiccube-vue3
Version:
vue3-js版组件库
187 lines (168 loc) • 6.17 kB
JavaScript
import { ref, computed, getCurrentInstance, watch, onMounted, onUnmounted } from 'vue'
import getFormValidMethod from '../../utils/form-valid'
import CLEAR_ICON from '../../img/icon_clear.svg'
const Input = {
name: 'McInput',
props: {
modelValue: [String, Number],
type: {
type: String,
default: 'text'
},
name: String,
readonly: Boolean,
disabled: Boolean,
placeholder: {
type: String,
default: '请输入'
},
autofocus: Boolean,
clear: Boolean,
prefixIcon: String,
suffixIcon: String,
click: {
type: Function,
default: () => { }
},
errorStatus: Boolean,
maxlength: Number,
unchecked: Boolean,
},
setup(props, { emit, slots }) {
const isFocus = ref(false)
const mouseIn = ref(false)
const inputEl = ref(null)
let isPinyinInput = null
const instance = getCurrentInstance()
const { fieldName, validator, errorMessage } = getFormValidMethod(instance)
const fieldError = computed(() => fieldName && errorMessage?.value && !props.unchecked ? errorMessage.value[fieldName] : '')
/* 监听外部改变参数 清空校验器报错 */
watch(() => props.modelValue, (n, o) => n && n !== o && validator && validator('change', n))
const model = computed({
get() {
return props.modelValue || props.modelValue === 0? props.modelValue : ''
},
set(value) {
emit('update:modelValue', value)
}
})
const handleKeyup = (e) => {
emit('keyup', e.target.value)
if(e.keyCode === 13) {
inputEl.value.blur()
}
}
const handleFocus = (e) => {
isFocus.value = true
emit('focus', e)
}
const handleBlur = (e) => {
model.value = e.target.value
isFocus.value = false
emit('change', model.value)
emit('blur', e)
validator && validator('blur', model.value)
}
const handleClear = (e) => {
e.stopPropagation()
model.value = ''
inputEl.value.focus()
emit('clear', e)
}
const handleInput = (e) => {
// 如果是拼音输入需要判断是不是拼音正在输入中
if(isPinyinInput) return
model.value = e.target.value
validator && validator('change', model.value)
}
// 拼音输入开始
const handlePinyinInputStart = () => {
isPinyinInput = true
}
// 拼音输入结束 结束后调用emit触发input事件 并进行赋值
const handlePinyinInputEnd = (e) => {
isPinyinInput = false
model.value = e.target.value
validator && validator('change', model.value)
emit('input', model.value)
}
// 监听拼音输入识别器事件compositionstart、compositionupdate、compositionend
onMounted(() => {
inputEl.value?.addEventListener?.('compositionstart', handlePinyinInputStart)
inputEl.value?.addEventListener?.('compositionend', handlePinyinInputEnd)
})
onUnmounted(() => {
inputEl.value?.removeEventListener?.('compositionstart', handlePinyinInputStart)
inputEl.value?.removeEventListener?.('compositionend', handlePinyinInputEnd)
})
return () => (
<div class={[
'mc-input',
{
'focus': isFocus.value || mouseIn.value,
'disabled': props.disabled,
'error': Boolean(fieldError.value) || props.errorStatus
}
]}
onMouseenter={() => mouseIn.value = true}
onMouseleave={() => mouseIn.value = false}>
{
slots.prefix? (
<i class="mc-input__prefix">
{slots.prefix()}
</i>
) : props.prefixIcon ? (
<i class="mc-input__prefix">
<img src={props.prefixIcon} />
</i>
) : ''
}
<input ref={inputEl} class="mc-input__inner"
v-model={model.value}
type={props.type}
{...props}
onFocus={handleFocus}
onBlur={handleBlur}
onClick={props.click}
onInput={handleInput}
onKeyup={handleKeyup}
autocomplete="off"
/>
{
props.clear && mouseIn.value && model.value ? (
<i class="mc-input__clear"
onClick={handleClear}>
<img src={CLEAR_ICON} />
</i>
) : ''
}
{
slots.suffix? (
<i class={[
'mc-input__suffix',
{
'has-clear': props.clear && mouseIn.value
}
]}>
{slots.suffix()}
</i>
) : props.suffixIcon ? (
<i class={[
'mc-input__suffix',
{
'has-clear': props.clear && mouseIn.value
}
]}>
<img src={props.suffixIcon} />
</i>
) : ''
}
</div>
)
}
}
Input.install = (app) => {
app.component(Input.name, Input)
}
const McInput = Input
export { McInput, McInput as default }