Javascript v-model和v-bind单选按钮上的值出现Vue JS prop错误="$attrs";
我有一种奇怪的行为,我无法控制 我有一个简单的单选按钮组件,用作实际单选按钮的“包装器” 在这个组件上,我有Javascript v-model和v-bind单选按钮上的值出现Vue JS prop错误="$attrs";,javascript,vue.js,Javascript,Vue.js,我有一种奇怪的行为,我无法控制 我有一个简单的单选按钮组件,用作实际单选按钮的“包装器” 在这个组件上,我有inheritAttrs:false并在元素本身上使用v-bind=“$attrs”,这样我就可以使用v-model和value等 但是,在选择单选按钮时,会抛出一个错误,即prop值无效(因为它是一个事件而不是字符串),有趣的是,我注意到在初始渲染时,Vue Devtools中prop值为空 我只是想让这些单选按钮用所选单选按钮的字符串值更新location的父级数据对象值 我不知道我到
inheritAttrs:false
并在元素本身上使用v-bind=“$attrs”
,这样我就可以使用v-model和value等
但是,在选择单选按钮时,会抛出一个错误,即prop值无效(因为它是一个事件而不是字符串),有趣的是,我注意到在初始渲染时,Vue Devtools中prop值为空
我只是想让这些单选按钮用所选单选按钮的字符串值更新location
的父级数据对象值
我不知道我到底错在哪里。非常感谢您的帮助
问题的示例项目:
FormMain.vue
<template>
<div>
<p>Location: {{ location }}</p>
<form-radio
id="location-chicago"
v-model="location"
value="Chicago"
name="location"
label="Chicago"
@change="changed"
/>
<form-radio
id="location-london"
v-model="location"
value="London"
name="location"
label="London"
@change="changed"
/>
</div>
</template>
<script>
import FormRadio from "./FormRadio.vue";
export default {
name: "FormMain",
components: {
FormRadio
},
data() {
return {
location: ""
};
},
methods: {
changed(e) {
console.log("Change handler says...");
console.log(e);
}
}
};
</script>
<template>
<div>
<label :for="id">
{{ label }}
<input
:id="id"
type="radio"
:value="value"
v-on="listeners"
v-bind="$attrs"
>
</label>
</div>
</template>
<script>
export default {
name: "FormRadio",
inheritAttrs: false,
props: {
id: {
type: String,
required: true
},
label: {
type: String,
required: true
},
value: {
type: String,
required: true
}
},
computed: {
listeners() {
return {
...this.$listeners,
change: event => {
console.log("Change event says...");
console.log(event.target.value);
this.$emit("change", event.target.value);
}
};
}
}
};
</script>
<form-radio
id="location-chicago"
v-model="location"
radio-value="Chicago"
name="location"
label="Chicago"
@change="changed"
/>
<form-radio
id="location-london"
v-model="location"
radio-value="London"
name="location"
label="London"
@change="changed"
/>
<template>
<div>
<label :for="(id) ? `field-${id}` : false">
{{ label }}
<input
:id="`field-${id}`"
type="radio"
:value="radioValue"
v-on="listeners"
v-bind="$attrs"
>
</label>
</div>
</template>
<script>
export default {
name: "FormRadio",
inheritAttrs: false,
props: {
id: {
type: String,
required: true
},
label: {
type: String,
required: true
},
radioValue: {
type: String,
required: true
}
},
computed: {
listeners() {
return {
...this.$listeners,
input: event => {
console.log("input event says...");
console.log(event.target.value);
this.$emit("input", event.target.value);
},
change: event => {
console.log("Change event says...");
console.log(event.target.value);
this.$emit("change", event.target.value);
}
};
}
}
};
</script>
位置:{{Location}
从“/FormRadio.vue”导入FormRadio;
导出默认值{
名称:"FormMain",,
组成部分:{
FormRadio
},
数据(){
返回{
地点:“
};
},
方法:{
更改(e){
log(“更改处理程序说…”);
控制台日志(e);
}
}
};
FormRadio.vue
<template>
<div>
<p>Location: {{ location }}</p>
<form-radio
id="location-chicago"
v-model="location"
value="Chicago"
name="location"
label="Chicago"
@change="changed"
/>
<form-radio
id="location-london"
v-model="location"
value="London"
name="location"
label="London"
@change="changed"
/>
</div>
</template>
<script>
import FormRadio from "./FormRadio.vue";
export default {
name: "FormMain",
components: {
FormRadio
},
data() {
return {
location: ""
};
},
methods: {
changed(e) {
console.log("Change handler says...");
console.log(e);
}
}
};
</script>
<template>
<div>
<label :for="id">
{{ label }}
<input
:id="id"
type="radio"
:value="value"
v-on="listeners"
v-bind="$attrs"
>
</label>
</div>
</template>
<script>
export default {
name: "FormRadio",
inheritAttrs: false,
props: {
id: {
type: String,
required: true
},
label: {
type: String,
required: true
},
value: {
type: String,
required: true
}
},
computed: {
listeners() {
return {
...this.$listeners,
change: event => {
console.log("Change event says...");
console.log(event.target.value);
this.$emit("change", event.target.value);
}
};
}
}
};
</script>
<form-radio
id="location-chicago"
v-model="location"
radio-value="Chicago"
name="location"
label="Chicago"
@change="changed"
/>
<form-radio
id="location-london"
v-model="location"
radio-value="London"
name="location"
label="London"
@change="changed"
/>
<template>
<div>
<label :for="(id) ? `field-${id}` : false">
{{ label }}
<input
:id="`field-${id}`"
type="radio"
:value="radioValue"
v-on="listeners"
v-bind="$attrs"
>
</label>
</div>
</template>
<script>
export default {
name: "FormRadio",
inheritAttrs: false,
props: {
id: {
type: String,
required: true
},
label: {
type: String,
required: true
},
radioValue: {
type: String,
required: true
}
},
computed: {
listeners() {
return {
...this.$listeners,
input: event => {
console.log("input event says...");
console.log(event.target.value);
this.$emit("input", event.target.value);
},
change: event => {
console.log("Change event says...");
console.log(event.target.value);
this.$emit("change", event.target.value);
}
};
}
}
};
</script>
{{label}}
导出默认值{
名称:“FormRadio”,
继承属性:false,
道具:{
身份证:{
类型:字符串,
必填项:true
},
标签:{
类型:字符串,
必填项:true
},
价值:{
类型:字符串,
必填项:true
}
},
计算:{
听众(){
返回{
…这.$listeners,
更改:事件=>{
log(“更改事件显示…”);
日志(event.target.value);
这是.emit(“change”,event.target.value);
}
};
}
}
};
我从子组件调用中完全删除了v-model(这是冲突的)
更新:链接到更新的编辑
<script>
export default {
name: "FormRadio",
inheritAttrs: false,
props: {
id: {
type: String,
required: true
},
label: {
type: String,
required: true
}
},
// customize the event/prop pair accepted by v-model
model: {
prop: "radioModel",
event: "radio-select"
},
computed: {
listeners() {
return {
...this.$listeners,
change: event => {
console.log("Change event says...");
console.log(event.target.value);
// emit the custom event to update the v-model value
this.$emit("radio-select", event.target.value);
// the change event that the parent was listening for
this.$emit("change", event.target.value);
}
};
}
}
};
</script>
找到了一篇描述组件的模型
属性的简洁文章。基本上,它允许您定制v-model
的工作方式。使用此选项,FormMain.vue
将不必更改。只需从FormRadio
中删除value prop,并使用您自己的定义添加model属性
见更新:
格式广播脚本
<script>
export default {
name: "FormRadio",
inheritAttrs: false,
props: {
id: {
type: String,
required: true
},
label: {
type: String,
required: true
}
},
// customize the event/prop pair accepted by v-model
model: {
prop: "radioModel",
event: "radio-select"
},
computed: {
listeners() {
return {
...this.$listeners,
change: event => {
console.log("Change event says...");
console.log(event.target.value);
// emit the custom event to update the v-model value
this.$emit("radio-select", event.target.value);
// the change event that the parent was listening for
this.$emit("change", event.target.value);
}
};
}
}
};
</script>
输入
事件处理程序将更新v模型
FormRadio.vue
<template>
<div>
<p>Location: {{ location }}</p>
<form-radio
id="location-chicago"
v-model="location"
value="Chicago"
name="location"
label="Chicago"
@change="changed"
/>
<form-radio
id="location-london"
v-model="location"
value="London"
name="location"
label="London"
@change="changed"
/>
</div>
</template>
<script>
import FormRadio from "./FormRadio.vue";
export default {
name: "FormMain",
components: {
FormRadio
},
data() {
return {
location: ""
};
},
methods: {
changed(e) {
console.log("Change handler says...");
console.log(e);
}
}
};
</script>
<template>
<div>
<label :for="id">
{{ label }}
<input
:id="id"
type="radio"
:value="value"
v-on="listeners"
v-bind="$attrs"
>
</label>
</div>
</template>
<script>
export default {
name: "FormRadio",
inheritAttrs: false,
props: {
id: {
type: String,
required: true
},
label: {
type: String,
required: true
},
value: {
type: String,
required: true
}
},
computed: {
listeners() {
return {
...this.$listeners,
change: event => {
console.log("Change event says...");
console.log(event.target.value);
this.$emit("change", event.target.value);
}
};
}
}
};
</script>
<form-radio
id="location-chicago"
v-model="location"
radio-value="Chicago"
name="location"
label="Chicago"
@change="changed"
/>
<form-radio
id="location-london"
v-model="location"
radio-value="London"
name="location"
label="London"
@change="changed"
/>
<template>
<div>
<label :for="(id) ? `field-${id}` : false">
{{ label }}
<input
:id="`field-${id}`"
type="radio"
:value="radioValue"
v-on="listeners"
v-bind="$attrs"
>
</label>
</div>
</template>
<script>
export default {
name: "FormRadio",
inheritAttrs: false,
props: {
id: {
type: String,
required: true
},
label: {
type: String,
required: true
},
radioValue: {
type: String,
required: true
}
},
computed: {
listeners() {
return {
...this.$listeners,
input: event => {
console.log("input event says...");
console.log(event.target.value);
this.$emit("input", event.target.value);
},
change: event => {
console.log("Change event says...");
console.log(event.target.value);
this.$emit("change", event.target.value);
}
};
}
}
};
</script>
{{label}}
导出默认值{
名称:“FormRadio”,
继承属性:false,
道具:{
身份证:{
类型:字符串,
必填项:true
},
标签:{
类型:字符串,
必填项:true
},
放射性值:{
类型:字符串,
必填项:true
}
},
计算:{
听众(){
返回{
…这.$listeners,
输入:事件=>{
log(“输入事件显示…”);
日志(event.target.value);
这是.emit(“输入”,event.target.value);
},
更改:事件=>{
log(“更改事件显示…”);
日志(event.target.value);
这是.emit(“change”,event.target.value);
}
};
}
}
};
请参见奇怪的是,您同时设置了
v-model
和value
-v-model
应该是值的真实来源,但是我如何指定每个单选按钮都有自己的值要设置?否则你会怎么做?我会建立一个示例答案…谢谢。如果您可以使用Codesandbox,那就太好了。您试图在两个不同的元素上使用相同的v-model
,这有点让人困惑,因为它会指定两个元素的值。我猜您是说手动操作?v-model应该可以工作……它可以通过这种方式使用单文本输入。如果我不为单选按钮使用包装器组件,而只是将它们放在具有相同属性的顶层,那么它甚至可以工作。可能是虫子?可能是。我对这件事了解得不够公正。我无法向您展示有效的解决方案,因为我不知道如何给出您的示例,我只能建议您尝试上面的编辑,看看它对您是否比对我更有意义。这在技术上是可行的……但我们失去了v-model为我们这样做的好处。我想我想避免手动同步数据中的属性。我想如果使用您的方法将location
设置为“Chicago”,您将如何防止这也应用于“London”?我猜这又回到了@DerekPollard所说的我明白了。谢谢你,这很有效。我想这是Vue的一个bug吗?我想这是设计的。据报道,组件包装了其他本机输入类型。我在GitHub上找到了这个