Consider a simple Vue component with text input (link).
<script setup>
import { ref } from 'vue'
const msg = ref('')
function onInput(e) {
let value = e.target.value;
if (value === ' ') value = '';
msg.value = value;
}
</script>
<template>
<input :value="msg" @input="onInput" />
</template>
I want to disable first space in this input, i.e. if a user inputs space then the inputfield should remain empty. But it doesn’t work. I guess it happens because Vue checks that msg
doesn’t change and rejects component render.
My next attempt is to force render the component (link).
<script setup>
import {getCurrentInstance} from 'vue'
import { ref } from 'vue'
const msg = ref('')
const instance = getCurrentInstance();
function onInput(e) {
let value = e.target.value;
if (value === ' ') {
value = '';
msg.value = value;
instance?.proxy?.$forceUpdate();
return;
}
msg.value = value;
}
</script>
<template>
<input :value="msg" @input="onInput" />
</template>
It works, but with limits. My project has a big tree of components and $forceUpdate
updates current component only without children.
I also tried to re-render the whole sub-three with changing key
on the component, but in this case I lose input’s focus.
To sum up, it seems that I miss something. I can’t believe that such simple task requires weird workarounds. Please help me to find a simple and “best practice” way to disable first space in html input.
P.S. React version works as expected.
import React, {useState} from 'react';
export function App(props) {
const [value, setValue] = useState('');
function onInput(e) {
let v = e.target.value;
if (v === ' ') v = '';
setValue(v);
}
return (
<div className='App'>
<input value={value} onInput={onInput} />
</div>
);
}
13
Based on your code: don’t react to the input event. It’s too late. React before the input event occurs. And filter out that space character.
This will save the application a lot of unnecessary calculations (msg=” “, then msg=””).
<script setup>
import { ref } from 'vue'
const msg = ref('')
const filterFirstSpace = e => {
const isEmpty = !e.target.value.length
const isSpace = /s/.test(e.data)
if (isEmpty && isSpace) {
e.preventDefault()
}
}
</script>
<template>
<input
:value="msg"
@beforeinput="filterFirstSpace"
/>
</template>
You can handle the @keydown event to detect if the first entered symbol is a space and prevent entering if so.
Here is an example:
<script setup>
import { ref } from "vue";
const msg = ref("");
function onInput(e) {
msg.value = e.target.value;
}
function preventLeadingSpace(e) {
if (msg.value.length === 0 && e.key === " ") {
e.preventDefault();
}
}
</script>
<template>
<input :value="msg" @input="onInput" @keydown="preventLeadingSpace" />
</template>
You should use a regular expression to remove the first whitespace character from the string.
const { createApp, ref } = Vue;
createApp({
setup() {
const inputValue = ref('');
const removeFirstSpace = () => {
// 使用正则表达式去除第一个空格
inputValue.value = inputValue.value.replace(/^s/, '');
};
return {
inputValue,
removeFirstSpace
};
}
}).mount('#app');
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vue 3 Input 示例</title>
<script src="https://unpkg.com/vue@3"></script>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
}
</style>
</head>
<body>
<div id="app">
<h1>输入示例</h1>
<input type="text" v-model="inputValue" @blur="removeFirstSpace" placeholder="输入一些内容">
<p>你输入的内容是: {{ inputValue }}</p>
</div>
</body>
</html>
young alan is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
2