具有单选按钮动态列表的 Vue.js v-model
Posted
技术标签:
【中文标题】具有单选按钮动态列表的 Vue.js v-model【英文标题】:Vue.js v-model with dynamic list of radio buttons 【发布时间】:2020-02-23 17:33:11 【问题描述】:我正在尝试制作一个可重用的 vue 单选按钮组件,该组件将采用变量名称和包含标签和值的对象,然后使用 v-for 呈现单选按钮列表。
我已经成功解决了问题的每一部分,但没有设法将它们结合起来:
-
我可以制作一组绑定到数据模型的单选按钮,这些按钮是在模板中静态定义的,但我不知道如何使列表动态化。下面是代码:
//component
const Radio =
template: '#test',
prop: ['value'],
data ()
return
selected: this.value
,
model:
prop: 'value',
event: 'change'
,
methods:
handleClickInput (e)
this.$emit('change', this.selected)
//app
var app2 = new Vue(
el: '#app2',
data:
door: '',
doorOptions:
'Yes': 1,
'No': 0,
,
components: Radio,
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app2">
<radio v-model="door"></radio>
<p>
door = door
</p>
</div>
<template id="test">
<div>
<input type="radio" value="0" v-model="selected" @change="handleClickInput">0
<input type="radio" value="1" v-model="selected" @change="handleClickInput">1
</div>
</template>
-
我可以根据“选项”对象制作单选按钮的动态列表,但找不到将它们绑定到数据模型的方法。下面是代码:
// component
Vue.component('radio-set',
template: '#radio-set',
props:
'label-name': '',
'variable': '',
'options': '',
,
methods:
clicked: function(variable, key, value)
// none of this is right, it doesn't update the vue data model
window[variable] = value; //assign the new value to the dynamic variable name
selected = value;
this.$emit("click-event", variable) //create the click event for model updating by the parent
,
)
//app
var app = new Vue(
el: '#vueApp',
data:
door:'initial value',
doorOptions:
'Yes':1,
'No':0,
'Maybe':5,
'A new option':25
,
,
methods:
buttonClick: function(p1)
console.log(p1+': '+window[p1]); //the variable was assigned inside the child component
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="vueApp">
<radio-set
label-name="Radio button set"
variable="door"
:options="doorOptions"
@click-event="buttonClick"
>door: door
</radio-set>
</div>
<template id="radio-set">
<div>
<label>labelName:</label>
<button
type="button"
v-for="(val, key) in options"
@click="clicked(variable, key, val)"
>
key
</button>
</div>
</template>
任何人都可以提供一些关于我如何前进的建议吗?
【问题讨论】:
【参考方案1】:正如@PierreSaid 所提到的,您可以阅读有关自定义组件上v-model
用法的更多信息。
这是另一个使用 input[type="radio"]
并将更改事件发送回父组件的示例。
// component
Vue.component('radio-set',
template: '#radio-set',
props:
'label-name': '',
'value': '',
'options': '',
)
//app
var app = new Vue(
el: '#vueApp',
data()
return
door: null,
doorOptions:
'Yes': 1,
'No': 0,
'Maybe': 5,
'A new option': 25
;
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<div id="vueApp">
<radio-set label-name="Radio button set" v-model="door" :options="doorOptions"></radio-set>
door: door
</div>
<template id="radio-set">
<div>
<div>labelName:</div>
<label v-for="(val, key) in options" :key="val">
<input type="radio"
:name="labelName"
:value="val"
:checked="val == value"
@change="$emit('input', val)">
key
</label>
</div>
</template>
【讨论】:
好答案,我使用[ ... , ... ]
等对象的数组/列表创建了一个版本,还有一个使用 Vuetify【参考方案2】:
首先:对于您的选择,拥有一个数组会更容易。
doorOptions: [
key: "Yes", value: 1 ,
key: "No", value: 0 ,
key: "Maybe", value: 5 ,
key: "A new option", value: 25
]
;
这样您就可以对其进行迭代。
使用v-model 也是在自定义组件和应用之间同步所选值的好方法。
A tutorial to implement v-model
这样我们就可以像这样创建一个可重用的组件:
<template>
<div>
<label>labelName:</label>
<button
type="button"
v-for="(val, idx) in options"
:key="idx"
@click="clicked(val)"
> val.key </button>
</div>
</template>
<script>
export default
props: ["value", "options", "labelName"],
methods:
clicked(val)
this.$emit("input", val);
;
</script>
并像这样使用它
<template>
<div id="app">
<radio-set v-model="selected" label-name="Radio button set" :options="doorOptions"/>
Selected : selected.key
</div>
</template>
<script>
import Radioset from "./components/RadioSet";
export default
name: "App",
components:
RadioSet
,
data()
return
selected: null,
doorOptions: [
key: "Yes", value: 1 ,
key: "No", value: 0 ,
key: "Maybe", value: 5 ,
key: "A new option", value: 25
]
;
;
</script>
Live demo
【讨论】:
【参考方案3】:当我研究和玩弄这些答案时,我想出了以下方法:
-
使用对象数组和Vuetify的首选方法:
new Vue(
el: '#app',
vuetify: new Vuetify(),
data: () => (
color:
label: "Choose:",
// Array List
items: [
key: 1, value: "Red", color: "red" ,
key: 2, value: "Green", color: "green" ,
key: 3, value: "Blue", color: "blue"
],
selectedItemKey: 2 // Red
),
computed:
selectedColorItem()
return this.color.items.find(item => item.key===this.color.selectedItemKey)
)
<div id="app">
<v-app id="inspire">
<v-container fluid mx-4>
<v-radio-group
:label="color.label"
row
v-model="color.selectedItemKey"
>
<v-radio
:color="item.color"
:key="item.key"
:label="item.value"
:value="item.key"
v-for="(item, index) in color.items"
></v-radio>
</v-radio-group>
Color: <span :class=`$selectedColorItem?.color--text`>
selectedColorItem?.value
</span>(key: color.selectedItemKey)
</v-container>
</v-app>
</div>
<link href="https://cdn.jsdelivr.net/npm/@mdi/font@3.x/css/materialdesignicons.min.css" rel="stylesheet"/>
<link href="https://cdn.jsdelivr.net/npm/vuetify@2.0.11/dist/vuetify.min.css" rel="stylesheet"/>
<script src="https://cdn.jsdelivr.net/npm/vue@2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.js"></script>
数组列表 & <label>
) - codepen
对象列表 & <Label>
) - codepen
我看了一下使用@Pierre Said 回答中的按钮,但似乎我需要使用一堆 CSS 来使按钮看起来像单选按钮。
【讨论】:
Vuetify 和 BootstrapVue 都提供灵活的无线电组组件。如果您的项目已经使用其中一个库,那么使用它们是有意义的。但是这个问题是关于从头开始创建一个可重用的无线电组组件。仅为其单选按钮加载一个 Vuetify 大小的库没有多大意义。除此之外,查看您列出的其他两个选项,它们似乎是对已接受答案的抄袭。当您“调整”并重新发布现有解决方案时,您应该正确地对其进行归因并准确阐明您对修改版本的贡献(如果有的话)。【参考方案4】:基于其他答案之一,我最终得到了 Vue 3。 v-model
的工作方式有一些重大变化,即在道具名称中。 (https://v3.vuejs.org/guide/migration/v-model.html)
样式是初级的,但我想要一些东西来表明活动选择是什么。
<template>
<div>
<label> labelName :</label>
<button
:class="val.key === modelValue ? 'active' : 'inactive'"
type="button"
v-for="(val, idx) in options"
:key="idx"
@click="clicked(val)"
>
val.key
</button>
</div>
</template>
<script>
export default
props: ["modelValue", "options", "labelName"],
methods:
clicked(val)
console.log("emitting click", val.key);
this.$emit("update:modelValue", val.key);
,
;
</script>
<style scoped>
button
padding: 10px;
margin: 5px;
.active
background-color: #42b983;
.inactive
background-color: lightgray;
</style>
它以相同的方式使用。我只是将一个基本数组映射到 key, value 因为这就是我所需要的,但是做一些更明确的事情会很容易。
<template>
<radio-set
label-name="On / Off"
v-model="myValue"
:options="options.radioOptions"
></radio-set>
</template>
<script>
import RadioSet from "./RadioSet.vue";
let options =
radioOptions: ["on", "off"].map((x) =>
return key: x, val: x ;
),
;
export default
name: "MyComponent",
components:
RadioSet,
,
data: () =>
return
options,
myValue: "unknown",
;
,
;
</script>
【讨论】:
以上是关于具有单选按钮动态列表的 Vue.js v-model的主要内容,如果未能解决你的问题,请参考以下文章
根据Android Studio中的字符串值动态添加单选按钮列表?
我无法将我的 v-model 数据传递到我的后端以获取 vue.js 中的单选按钮类型,如何将选中的单选按钮值传递给我的后端?