【发布时间】:2021-12-03 21:39:39
【问题描述】:
我在尝试在 Vue 3 中制作自定义表单组件时关注了this guide(组合 API,script setup 模式)。
当我加载包含我的组件的页面时,我收到如下控制台警告:
[Vue 警告]:缺少必需的道具:“值” 在
我的组件(CSS 省略):
<template>
<input ref="switchElement"
v-bind="$attrs"
class="gui-switch"
@input="value = !value; emit('update:modelValue', value)"
type="checkbox"
role="switch"
:value="value" />
</template>
<script setup lang="ts">
import { defineEmit, defineProps, onMounted, ref } from "vue"
const props = defineProps<{
value: boolean | undefined,
}>()
const emit = defineEmit<{
(e: "update:modelValue", value: boolean | undefined): void,
}>()
const switchElement = ref<HTMLInputElement>()
onMounted(() => switchElement.value!.indeterminate = true)
</script>
包含它的页面像这样使用它:
<!-- v-for question in questions -->
<switch-control :name="`question-${question.id}`"
:model="feedbackData[`question-${question.id}`]"
:id="`question-${question.id}`" />
我尝试了各种方法,例如将发出的事件的名称更改为 input 或使用 v-model 而不是 :model 但我还没有设法解决这个问题,我不知道还有什么试试看。
编辑:
因此编辑组件以使用modelValue:
<template>
<input ref="switchElement"
v-bind="$attrs"
class="gui-switch"
@input="modelValue = !modelValue; emit('update:modelValue', modelValue)"
type="checkbox"
role="switch"
:value="modelValue" />
</template>
<script setup lang="ts">
import { defineEmit, defineProps, onMounted, ref } from "vue"
const props = defineProps<{
modelValue: boolean | undefined,
}>()
const emit = defineEmit<{
(e: "update:modelValue", value: boolean | undefined): void,
}>()
const switchElement = ref<HTMLInputElement>()
onMounted(() => switchElement.value!.indeterminate = true)
</script>
家长:
<!-- v-for question in questions -->
<switch-control :name="`question-${question.id}`"
v-model="feedbackData[`question-${question.id}`]"
:id="`question-${question.id}`" />
导致彻底错误:
[Vue warn]: Unhandled error during execution of scheduler flush. This is likely a Vue internals bug. Please open an issue at https://new-issue.vuejs.org/?repo=vuejs/vue-next
at <SwitchControl key=0 name="question-8" modelValue=undefined ... >
Uncaught (in promise) TypeError: invalid 'instanceof' operand type
assertType runtime-core.esm-bundler.js:1877
validateProp runtime-core.esm-bundler.js:1841
validateProps runtime-core.esm-bundler.js:1817
initProps runtime-core.esm-bundler.js:1548
setupComponent runtime-core.esm-bundler.js:6500
mountComponent runtime-core.esm-bundler.js:4206
processComponent runtime-core.esm-bundler.js:4182
patch runtime-core.esm-bundler.js:3791
mountChildren runtime-core.esm-bundler.js:3975
EDIT2: 我设法放大了问题所在,但我仍然无法完全弄清楚发生了什么。
我更改了组件,使 @input 现在是 @input="emit('update:modelValue', !modelValue)"。我将包含包含它的页面的<script> 的相关部分:
import SwitchControl from "@/components/SwitchControl.vue"
import type { FeedbackQuestion } from "@/utils/api/story"
import { defineProps, ref } from "vue"
const props = defineProps<{
questions: {id: number}[],
}>()
const defaultModelValues = {
// These are hard-coded for debugging, ideally I'd want it to work with an empty initial object
"question-8": null,
"question-11": null,
}
const feedbackData = ref<Record<string, any>>(defaultModelValues)
现在的症状:
- 当代码如上所示,prop 和 emit 定义为
boolean | undefined时,我收到以下错误并且整个 for 循环未呈现:
[Vue warn]: Unhandled error during execution of scheduler flush. This is likely a Vue internals bug. Please open an issue at https://new-issue.vuejs.org/?repo=vuejs/vue-next
at <SwitchControl modelValue=null onUpdate:modelValue=fn<onUpdateModelValue> name="question-8" ... >
Uncaught (in promise) TypeError: invalid 'instanceof' operand type
- 如果我将 prop 注释并作为
boolean发出,则元素会加载,我只会收到警告(见下文)。如果我然后尝试通过单击元素来更改值,我会不断收到相同的警告,并且值根本不会改变,而不是像预期的那样交替 true 和 false。如果我检查 HTML 中的value属性,它的行为确实正确(最初是“”,然后在“真”和“假”之间交替)。
[Vue warn]: Invalid prop: type check failed for prop "modelValue". Expected Boolean, got Null
at <SwitchControl modelValue=null onUpdate:modelValue=fn<onUpdateModelValue> name="question-8" ... >
【问题讨论】:
-
我无法重现此demo 中的问题。另请注意,道具是只读的,因此您的
@input处理程序不应尝试切换modelValue。 -
@tony19 请参阅问题的 EDIT2,也许它会暗示我没有考虑的事情。感谢您抽出宝贵的时间。
-
我无法在此demo 中重现 EDIT2 问题。你能分享一个复制的链接吗?
-
我创建了这个demo,尽可能地复制了我的实际应用程序的结构,但即使我的应用程序出错,它仍然不会出错。您对可能导致问题的事情有任何建议吗?我已经没有东西可以尝试了。常量是错误
Uncaught (in promise) TypeError: invalid 'instanceof' operand type,但我没有调用任何承诺,堆栈跟踪没有指向我自己代码中的任何地方,只有 esm-bundler。 -
只有当我将
modelValue类型更改为删除undefined时,该错误才会消失,但随后我会收到警告,因为该道具收到未定义而不是布尔值。然后我必须硬编码要给出的初始模型值,如果我尝试从道具动态派生它们,如下所示:feedbackData.value = Object.fromEntries(props.questions.map((q) => [question-${q.id}, false]))我再次收到警告:生成的对象记录为完全是空的,props.questions本身也是如此。如果我记录传递给:questions的对象,它确实包含预期的问题数组...
标签: vue.js data-binding custom-controls vuejs3 vue-composition-api