मैंने एक घटक बनाया है जो एक सरणी के बजाय एक स्ट्रिंग को बाध्य करने के अलावा सही काम करता है। घटना की आग सही ढंग से है।
तो बहु-चयन संस्करण पर यदि मैं आइटम का चयन और चयन रद्द करता हूं तो 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 जवाब
v-model
कस्टम घटक पर उम्मीद करता है कि घटक input
घटना का उत्सर्जन करेगा, न कि value
आपके घटक के बहु-चयन मोड में काम करने का एकमात्र कारण यह है कि आप सीधे value
प्रोप द्वारा दिए गए इनपुट सरणी को बदल रहे हैं (दूसरे शब्दों में उत्सर्जित घटना बेकार है)। ऐसा मत करो। उत्सर्जित करने से पहले एक नई सरणी बनाएं
साथ ही, एकल-चयन मोड के साथ एक और समस्या है - केवल चेक किए गए बॉक्स को अचयनित करने के बाद, आप अभी भी मान उत्सर्जित कर रहे हैं ताकि मॉडल मान पर सेट हो, यहां तक कि चेकबॉक्स में से कोई भी चेक नहीं किया गया है
व्यक्तिगत रूप से मुझे आपका डिज़ाइन कई कारणों से अजीब लगता है:
- भिन्न
v-model
"प्रकार" (सरणी या स्ट्रिंग) का उपयोग करना अप्राकृतिक लगता है - एकल-चयन मोड में यह रेडियो के रूप में व्यवहार करता है तो रेडियो का उपयोग क्यों न करें
- यदि आप रनटाइम पर
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>
आप ईवेंट और ट्रिगर विधि की प्रतीक्षा कर सकते हैं:
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>
current = [$event.target.value];