Vue3+Ts封装input组件时遇到的问题

使用input事件监听输入框变化时,如果当前使用的输入法是中文,他也会触发input事件,正常来说,中文没有输入完毕是不用触发事件的。

控制台打印时发现:

那么我们应该怎么去规避这件事呢?

其实input还有几个事件:

  • compositionstart:事件在用户开始使用输入法输入时触发。
  • onCompositionUpdate:事件在用户正在使用输入法输入时触发
  • compositionend: 事件在用户完成使用输入法输入时触发

 我们可以建立一个全局变量

const isComposing = ref(false);

在handleCompositionStart和handleCompositionEnd的事件中更改这个全局变量

const handleCompositionStart = () => {
	isComposing.value = true;
};

const handleCompositionEnd = (event: Event) => {
	isComposing.value = false;
};

在input事件中判断是否是中文输入法输入中的状态

const input = (event: Event) => {
	if (isComposing.value) {
		return;
	}
	const value = (event.target as HTMLInputElement).value;
	emit("update:modelValue", value);
	emit("change", value); // 添加此行代码
};

最后在handleCompositionEnd事件中添加如下代码:

const handleCompositionEnd = (event: Event) => {
	isComposing.value = false;
	const value = (event.target as HTMLInputElement).value;
	emit("update:modelValue", value);
	emit("change", value);
};

最后即可解决这个问题!

最后附上我封装的input组件(若觉得组件功能不完善,可以自行扩展组件)

MyInput.vue

<template>
	<div class="input-wrapper" :class="{ 'is-focused': isFocused }">
		<span class="prefix">
			<slot name="prefix"></slot>
		</span>
		<input
			:type="type"
			@input="input"
			:placeholder="placeholder"
			:disabled="disabled"
			:readonly="readonly"
			:maxlength="maxlength"
			@focus="handleFocus"
			@blur="handleBlur"
			@compositionstart="handleCompositionStart"
			@compositionend="handleCompositionEnd"
		/>
		<span class="suffix">
			<slot name="suffix"></slot>
		</span>
	</div>
</template>

<script setup lang="ts">
import { ref } from "vue";

const isFocused = ref(false);
const isComposing = ref(false);

const props = defineProps<{
	type?: string;
	modelValue: string;
	placeholder?: string;
	disabled?: boolean;
	readonly?: boolean;
	maxlength?: number;
}>();

const handleFocus = () => {
	isFocused.value = true;
};

const handleBlur = () => {
	isFocused.value = false;
};

const emit = defineEmits<{
	(e: "update:modelValue", value: string): void;
	(e: "change", value: string): void;
}>();

// 监听是否是中文输入事件
const handleCompositionStart = () => {
	isComposing.value = true;
};

const handleCompositionEnd = (event: Event) => {
	isComposing.value = false;
	const value = (event.target as HTMLInputElement).value;
	emit("update:modelValue", value);
	emit("change", value);
};

const input = (event: Event) => {
	if (isComposing.value) {
		return;
	}
	const value = (event.target as HTMLInputElement).value;
	emit("update:modelValue", value);
	emit("change", value);
};
</script>

<style scoped>
.input-wrapper {
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 1px 11px;
	border-radius: 10px;
	box-shadow: 0 0 0 1px #b5b5b5 inset;
}
.input-wrapper.is-focused {
	box-shadow: 0 0 0 2px #2478f2 inset;
}
input {
	width: 100%;
	flex-grow: 1;
	padding: 0;
	outline: 0;
	border: none;
	background: 0 0;
	box-sizing: border-box;
	outline: 0;
	font-size: 14px;
	line-height: 30px;
}

input:disabled {
	background-color: #000000;
	cursor: not-allowed;
}

input[readonly] {
	background-color: #000000;
	cursor: default;
}
.prefix {
	margin-right: 8px;
}
.suffix {
	margin-left: 8px;
}
</style>

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值