You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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 $emit lets children communicate state changes up to the parent, which is the standard Vue way of handling child-to-parent communication.
  • The disabled prop passes the parent's state back down to each child, ensuring all inputs stay in sync.

内容的提问来源于stack exchange,提问作者theMaertin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:13:36