Vue 2:多组件场景下输入框互斥禁用功能实现求助
Hey there! Let's tackle this Vue 2 problem you're facing—disabling other autocomplete inputs as soon as one input has its first character typed. The core issue here is tracking a shared state across all your Autocomplete components, so let's break down a clean solution that uses parent-component state management (no need for Vuex unless your app is large-scale).
The Approach
We'll have the parent component manage a "lock" state that tells all child inputs whether they should be disabled. Each Autocomplete child will notify the parent when it receives its first character input, and the parent will flip the lock to disable all other inputs. We can also add logic to re-enable inputs if the active one is cleared.
Step 1: Update the Autocomplete Child Component
First, modify your Autocomplete component to emit events when it starts receiving input or gets cleared, and accept a disabled prop to control its state:
<template> <input v-model="localValue" :disabled="disabled" @input="handleInput" placeholder="Type something..." /> <!-- Keep your existing autocomplete dropdown logic here --> </template> <script> export default { name: "autocomplete", props: { items: { type: Array, required: false, default: () => ['test'] }, isAsync: { type: Boolean, default: false }, // New prop to control input disable state disabled: { type: Boolean, default: false } }, data() { return { localValue: '' } }, methods: { handleInput() { // Emit event when first character is typed if (this.localValue.length === 1) { this.$emit('input-activated'); } // Emit event when input is cleared completely if (this.localValue.length === 0) { this.$emit('input-cleared'); } } } } </script>
Step 2: Manage State in the Parent Component
In the parent component that renders multiple Autocomplete instances, add a data property to track the active input lock, and handle the events emitted by the children:
<template> <div class="input-group"> <Autocomplete :disabled="inputLockActive" @input-activated="lockInputs" @input-cleared="unlockInputs" /> <Autocomplete :disabled="inputLockActive" @input-activated="lockInputs" @input-cleared="unlockInputs" /> <Autocomplete :disabled="inputLockActive" @input-activated="lockInputs" @input-cleared="unlockInputs" /> </div> </template> <script> import Autocomplete from './Autocomplete.vue'; export default { components: { Autocomplete }, data() { return { inputLockActive: false } }, methods: { lockInputs() { // Flip the lock to disable all other inputs this.inputLockActive = true; }, unlockInputs() { // Optional: Re-enable inputs only if ALL inputs are cleared // For simplicity, this example unlocks when any input is cleared // To make it stricter, you could check all child inputs' values via refs this.inputLockActive = false; } } } </script>
Optional: Keep the Active Input Enabled
If you want the first input that was typed into to stay enabled (while others are disabled), adjust the parent logic to track which input is active instead of a simple boolean:
<template> <div class="input-group"> <Autocomplete :disabled="activeInputId !== 'input-1' && activeInputId !== null" @input-activated="() => setActiveInput('input-1')" @input-cleared="() => clearActiveInput('input-1')" /> <Autocomplete :disabled="activeInputId !== 'input-2' && activeInputId !== null" @input-activated="() => setActiveInput('input-2')" @input-cleared="() => clearActiveInput('input-2')" /> </div> </template> <script> // ... (component import remains the same) export default { components: { Autocomplete }, data() { return { activeInputId: null } }, methods: { setActiveInput(id) { this.activeInputId = id; }, clearActiveInput(id) { if (this.activeInputId === id) { this.activeInputId = null; } } } } </script>
Why This Works
- The parent component acts as the single source of truth for input state, which avoids the confusion of trying to sync state between child components directly.
- Using
$emitlets children communicate state changes up to the parent, which is the standard Vue way of handling child-to-parent communication. - The
disabledprop passes the parent's state back down to each child, ensuring all inputs stay in sync.
内容的提问来源于stack exchange,提问作者theMaertin

