मैंने एक घटक बनाया है जो एक सरणी के बजाय एक स्ट्रिंग को बाध्य करने के अलावा सही काम करता है। घटना की आग सही ढंग से है।

तो बहु-चयन संस्करण पर यदि मैं आइटम का चयन और चयन रद्द करता हूं तो multiSelected चर सही ढंग से अपडेट किया जाता है। हालांकि एकल चयन के भीतर एक और मान का चयन करते समय singleSelected चर को नहीं बदला जा रहा है, हालांकि वही घटना सक्रिय हो रही है।

यहां कोड को कम कर दिया ताकि आप केवल तर्क और समस्या देख सकें:

Vue.component('dropdown', {
  template: `<div class="dropdown">
    <label v-for="item in items" :key="item.value" :class="{selected:selected.indexOf(item.value) > -1}">
      {{ item.label }}
      <input type="checkbox" :value="item.value" :checked="selected.indexOf(item.value) > -1" @change="selected = $event" />
    </label>
  </div>`,
  props: [ 'value', 'items', 'multiSelect' ],
  computed: {
    selected: {
      get: function() {
        if (this.value === undefined) {
          return [];
        }
        if (!Array.isArray(this.value)) {
          return [ this.value ];
        }
        return this.value;
      },
      set: function($event) {
        let current = this.selected;

        if (!this.multiSelect) {
          current = $event.target.value;
        }

        if (this.multiSelect && !$event.target.checked) {
          const index = current.indexOf($event.target.value);
          if (index > -1) {
            current.splice(index, 1)
          }
        }
        if (this.multiSelect && $event.target.checked) {
          current.push($event.target.value);
        }

        console.log(current);
        this.$emit('value', current);
      }
    }
  }
});

Vue.component('wrapper', {
  template: `
    <div>
      Single
      <dropdown :items="items" v-model="singleSelected" :multi-select="false" name="single" />
      <br />
      Multi
      <dropdown :items="items" v-model="multiSelected" :multi-select="true" name="multi" />
      <p>Models</p>
      <p>singleSelected: {{ singleSelected }}</p>
      <p>multiSelected: {{ multiSelected }}</p>
    </div>
  `,
  data() {
    return {
      items: [{value:'bmw',label:'BMW',count:1},{value:'audi',label:'Audi',count:1},{value:'kia',label:'KIA',count:1}],
      multiSelected: ['kia'],
      singleSelected: 'kia',
    }
  }
});

new Vue().$mount('#app');
.dropdown {
  border: 1px solid black;
  padding: 10px;
  display: block;
}
label {
  margin: 5px;
}


.selected {
  color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <wrapper>
    
  </wrapper>
</div>
2
Martyn Ball 7 जिंदा 2022, 16:15
आपको एक सरणी का उपयोग करना चाहिए - current = [$event.target.value];
 – 
IVO GELOV
7 जिंदा 2022, 17:09

2 जवाब

सबसे बढ़िया उत्तर

v-model कस्टम घटक पर उम्मीद करता है कि घटक input घटना का उत्सर्जन करेगा, न कि value

आपके घटक के बहु-चयन मोड में काम करने का एकमात्र कारण यह है कि आप सीधे value प्रोप द्वारा दिए गए इनपुट सरणी को बदल रहे हैं (दूसरे शब्दों में उत्सर्जित घटना बेकार है)। ऐसा मत करो। उत्सर्जित करने से पहले एक नई सरणी बनाएं

साथ ही, एकल-चयन मोड के साथ एक और समस्या है - केवल चेक किए गए बॉक्स को अचयनित करने के बाद, आप अभी भी मान उत्सर्जित कर रहे हैं ताकि मॉडल मान पर सेट हो, यहां तक ​​​​कि चेकबॉक्स में से कोई भी चेक नहीं किया गया है

व्यक्तिगत रूप से मुझे आपका डिज़ाइन कई कारणों से अजीब लगता है:

  1. भिन्न v-model "प्रकार" (सरणी या स्ट्रिंग) का उपयोग करना अप्राकृतिक लगता है
  2. एकल-चयन मोड में यह रेडियो के रूप में व्यवहार करता है तो रेडियो का उपयोग क्यों न करें
  3. यदि आप रनटाइम पर multiSelect प्रोप स्विच करते हैं तो क्या होगा?
Vue.component('dropdown', {
  template: `<div class="dropdown">
    <label v-for="item in items" :key="item.value" :class="{selected:selected.indexOf(item.value) > -1}">
      {{ item.label }}
      <input type="checkbox" :value="item.value" :checked="selected.indexOf(item.value) > -1" @change="selected = $event" />
    </label>
  </div>`,
  props: [ 'value', 'items', 'multiSelect' ],
  computed: {
    selected: {
      get: function() {
        if (this.value === undefined) {
          return [];
        }
        if (!Array.isArray(this.value)) {
          return [ this.value ];
        }
        return this.value;
      },
      set: function($event) {
        if(this.multiSelect) {
          if (!$event.target.checked) {
            this.$emit('input', this.selected.filter(v => v !== $event.target.value))
          } else {
            this.$emit('input', [...this.selected, $event.target.value])
          }
        } else {
          this.$emit('input', $event.target.checked ? $event.target.value : "")
        }
      }
    }
  }
});

Vue.component('wrapper', {
  template: `
    <div>
      Single
      <dropdown :items="items" v-model="singleSelected" :multi-select="false" name="single" />
      <br />
      Multi
      <dropdown :items="items" v-model="multiSelected" :multi-select="true" name="multi" />
      <p>Models</p>
      <p>singleSelected: {{ singleSelected }}</p>
      <p>multiSelected: {{ multiSelected }}</p>
    </div>
  `,
  data() {
    return {
      items: [{value:'bmw',label:'BMW',count:1},{value:'audi',label:'Audi',count:1},{value:'kia',label:'KIA',count:1}],
      multiSelected: ['kia'],
      singleSelected: 'kia',
    }
  }
});

new Vue().$mount('#app');
.dropdown {
  border: 1px solid black;
  padding: 10px;
  display: block;
}
label {
  margin: 5px;
}


.selected {
  color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <wrapper>
    
  </wrapper>
</div>
1
Michal Levý 7 जिंदा 2022, 17:48
धन्यवाद, यह मेरी ओर से एक मूर्खतापूर्ण गलती थी, मुझे उस घटना की दोबारा जांच करनी चाहिए थी जो मैं उत्सर्जित कर रहा था।
 – 
Martyn Ball
7 जिंदा 2022, 17:45

आप ईवेंट और ट्रिगर विधि की प्रतीक्षा कर सकते हैं:

Vue.component('dropdown', {
  template: `<div class="dropdown">
    <label v-for="item in items" :key="item.value" :class="{selected:selected.indexOf(item.value) > -1}">
      {{ item.label }}
      <input type="checkbox" :value="item.value" :checked="selected.indexOf(item.value) > -1" @change="selected = $event" />
    </label>
  </div>`,
  props: [ 'value', 'items', 'multiSelect' ],
  computed: {
    selected: {
      get: function() {
        if (this.value === undefined) {
          return [];
        }
        if (!Array.isArray(this.value)) {
          return [ this.value ];
        }
        return this.value;
      },
      set: function($event) {
        let current = this.selected;

        if (!this.multiSelect) {
          current = $event.target.value;
        }

        if (this.multiSelect && !$event.target.checked) {
          const index = current.indexOf($event.target.value);
          if (index > -1) {
            current.splice(index, 1)
          }
        }
        if (this.multiSelect && $event.target.checked) {
          current.push($event.target.value);
        }

        console.log(current);
        this.$emit('value', current);
      }
    }
  }
});

Vue.component('wrapper', {
  template: `
    <div>
      Single
      <dropdown :items="items" v-model="singleSelected" :multi-select="false" name="single" @value="updateSingle" />
      <br />
      Multi
      <dropdown :items="items" v-model="multiSelected" :multi-select="true" name="multi"  />
      <p>Models</p>
      <p>singleSelected: {{ singleSelected }}</p>
      <p>multiSelected: {{ multiSelected }}</p>
    </div>
  `,
  data() {
    return {
      items: [{value:'bmw',label:'BMW',count:1},{value:'audi',label:'Audi',count:1},{value:'kia',label:'KIA',count:1}],
      multiSelected: ['kia'],
      singleSelected: 'kia',
    }
  },
  methods: {
    updateSingle(val) {
      this.singleSelected = val
    }
  }
});

new Vue().$mount('#app');
.dropdown {
  border: 1px solid black;
  padding: 10px;
  display: block;
}
label {
  margin: 5px;
}


.selected {
  color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <wrapper>
    
  </wrapper>
</div>
0
Nikola Pavicevic 7 जिंदा 2022, 17:20