为什么 Input 不将输入的数据存储在 modelValue Prop 中
Why does Input not storing inputted data in modelValue Prop
我已经阅读了 Vue 3 上关于 v-model
和 :value
的几篇文章。
但是 none 在这种情况下确实帮助了我。
我想在 modelValue
prop 中存储值,并希望在用户更新或输入时更新它。
此代码运行没有任何错误,但在 Vue 3 开发控制台中显示 modelValue: undefined
。
我的 Vue 代码:
<template>
<span :class="wrapperClass">
<i :class="iconLeft" v-if="iconLeft" />
<InputText
:type="type"
:value="modelValue"
:class="{ 'p-filled': filled }"
@input="onInput"
/>
<label for="username">{{ label }}</label>
<i :class="iconRight" v-if="iconRight" />
</span>
</template>
<script lang="ts">
import InputText from "primevue/inputtext"
import { defineComponent } from "vue"
export default defineComponent({
name: "FormInput",
emits: ["update:modelValue"],
components: { InputText },
props: {
iconLeft: {
type: String,
default: "",
},
iconRight: {
type: String,
default: "",
},
error: {
type: String,
default: "",
},
label: {
type: String,
default: "",
},
type: {
type: String,
},
modelValue: {
type: String,
},
},
computed: {
wrapperClass(): any {
return {
"p-float-label": true,
"p-input-icon-left": this.iconLeft,
"p-input-icon-right": this.iconRight,
}
},
filled(): any {
return this.modelValue != null && this.modelValue.toString().length > 0
},
},
methods: {
onInput(event: any): any {
this.$emit("update:modelValue", event.target.value)
},
},
})
</script>
父组件:
<template>
<div class="home">
<Example :example="{ heading: 'fii' }" />
<Button label="Test" />
<hr />
<img alt="Vue logo" src="../assets/logo.png" />
<hr />
<FormInput v-bind="args" />
<hr />
<HelloWorld msg="Welcome to Your Vue.js + TypeScript App" />
</div>
</template>
<script lang="ts">
import { defineComponent } from "vue"
import HelloWorld from "../components/HelloWorld.vue" // @ is an alias to /src
import Example from "../components/Example/Example.vue" // @ is an alias to /src
import FormInput from "../components/Form/FormInput.vue"
export default defineComponent({
name: "Home",
components: {
HelloWorld,
Example,
FormInput,
},
setup() {
return {
args: {
label: "test",
type: "text",
value: "",
},
}
},
})
</script>
请看这张截图
开发控制台中的父组件
需要解决的问题很少:
PrimeVue组件InputText
没有道具value
但是modelValue
(支持v-model
)-InputText Docs + read Using v-model on Components学习区别本机输入 v-model
与自定义组件之间
InputText
不是原生 input
元素,因此没有必要监听 input
事件。该组件正在发出 update:modelValue
事件。此外,事件负载不是本机事件,因此 event.target.value
没有意义,只需使用 value
- source
没有必要复制 p-filled
,因为 InputText
已经这样做了(参见上面的来源)
// FormInput.vue
<template>
<span :class="wrapperClass">
<i :class="iconLeft" v-if="iconLeft" />
<InputText
:type="type"
:modelValue="modelValue"
@update:model-value="onInput"
/>
<label for="username">{{ label }}</label>
<i :class="iconRight" v-if="iconRight" />
</span>
</template>
<script lang="ts">
import InputText from "primevue/inputtext"
import { defineComponent } from "vue"
export default defineComponent({
name: "FormInput",
emits: ["update:modelValue"],
components: { InputText },
props: {
iconLeft: {
type: String,
default: "",
},
iconRight: {
type: String,
default: "",
},
error: {
type: String,
default: "",
},
label: {
type: String,
default: "",
},
type: {
type: String,
default: "text"
},
modelValue: {
type: String,
required: true
},
},
computed: {
wrapperClass(): any {
return {
"p-float-label": true,
"p-input-icon-left": this.iconLeft,
"p-input-icon-right": this.iconRight,
}
},
},
methods: {
onInput(value: any): any {
this.$emit("update:modelValue", value)
},
},
})
</script>
用法:
<FormInput v-model="data" />
<!-- OR -->
<FormInput :modelValue="data" @update:model-value="data = $event" />
演示:
const app = Vue.createApp({
data() {
return {
text: "default value",
}
},
});
app.component('FormInput', {
emits: ["update:modelValue"],
components: {
'inputtext': primevue.inputtext
},
template: `
<span :class="wrapperClass">
<i :class="iconLeft" v-if="iconLeft" />
<inputtext
:type="type"
:modelValue="modelValue"
@update:model-value="onInput"
></inputtext>
<label for="username">{{ label }}</label>
<i :class="iconRight" v-if="iconRight" />
</span>
`,
props: {
iconLeft: {
type: String,
default: "",
},
iconRight: {
type: String,
default: "",
},
error: {
type: String,
default: "",
},
label: {
type: String,
default: "",
},
type: {
type: String,
default: "text"
},
modelValue: {
type: String,
required: true
},
},
computed: {
wrapperClass() {
return {
"p-float-label": true,
"p-input-icon-left": this.iconLeft,
"p-input-icon-right": this.iconRight,
}
},
},
methods: {
onInput(value) {
this.$emit("update:modelValue", value)
},
},
});
app.mount('#app');
<link href="https://unpkg.com/primevue/resources/themes/saga-blue/theme.css" rel="stylesheet">
<link href="https://unpkg.com/primevue/resources/primevue.min.css" rel="stylesheet">
<link href="https://unpkg.com/primeicons/primeicons.css" rel="stylesheet">
<script src="https://unpkg.com/vue@next"></script>
<script src="https://unpkg.com/primevue/inputtext/inputtext.min.js"></script>
<div id="app">
<form-input v-model="text"></form-input>
<pre>
{{ text }}
</pre>
</div>
我已经阅读了 Vue 3 上关于 v-model
和 :value
的几篇文章。
但是 none 在这种情况下确实帮助了我。
我想在 modelValue
prop 中存储值,并希望在用户更新或输入时更新它。
此代码运行没有任何错误,但在 Vue 3 开发控制台中显示 modelValue: undefined
。
我的 Vue 代码:
<template>
<span :class="wrapperClass">
<i :class="iconLeft" v-if="iconLeft" />
<InputText
:type="type"
:value="modelValue"
:class="{ 'p-filled': filled }"
@input="onInput"
/>
<label for="username">{{ label }}</label>
<i :class="iconRight" v-if="iconRight" />
</span>
</template>
<script lang="ts">
import InputText from "primevue/inputtext"
import { defineComponent } from "vue"
export default defineComponent({
name: "FormInput",
emits: ["update:modelValue"],
components: { InputText },
props: {
iconLeft: {
type: String,
default: "",
},
iconRight: {
type: String,
default: "",
},
error: {
type: String,
default: "",
},
label: {
type: String,
default: "",
},
type: {
type: String,
},
modelValue: {
type: String,
},
},
computed: {
wrapperClass(): any {
return {
"p-float-label": true,
"p-input-icon-left": this.iconLeft,
"p-input-icon-right": this.iconRight,
}
},
filled(): any {
return this.modelValue != null && this.modelValue.toString().length > 0
},
},
methods: {
onInput(event: any): any {
this.$emit("update:modelValue", event.target.value)
},
},
})
</script>
父组件:
<template>
<div class="home">
<Example :example="{ heading: 'fii' }" />
<Button label="Test" />
<hr />
<img alt="Vue logo" src="../assets/logo.png" />
<hr />
<FormInput v-bind="args" />
<hr />
<HelloWorld msg="Welcome to Your Vue.js + TypeScript App" />
</div>
</template>
<script lang="ts">
import { defineComponent } from "vue"
import HelloWorld from "../components/HelloWorld.vue" // @ is an alias to /src
import Example from "../components/Example/Example.vue" // @ is an alias to /src
import FormInput from "../components/Form/FormInput.vue"
export default defineComponent({
name: "Home",
components: {
HelloWorld,
Example,
FormInput,
},
setup() {
return {
args: {
label: "test",
type: "text",
value: "",
},
}
},
})
</script>
请看这张截图
开发控制台中的父组件
需要解决的问题很少:
PrimeVue组件
InputText
没有道具value
但是modelValue
(支持v-model
)-InputText Docs + read Using v-model on Components学习区别本机输入v-model
与自定义组件之间InputText
不是原生input
元素,因此没有必要监听input
事件。该组件正在发出update:modelValue
事件。此外,事件负载不是本机事件,因此event.target.value
没有意义,只需使用value
- source没有必要复制
p-filled
,因为InputText
已经这样做了(参见上面的来源)
// FormInput.vue
<template>
<span :class="wrapperClass">
<i :class="iconLeft" v-if="iconLeft" />
<InputText
:type="type"
:modelValue="modelValue"
@update:model-value="onInput"
/>
<label for="username">{{ label }}</label>
<i :class="iconRight" v-if="iconRight" />
</span>
</template>
<script lang="ts">
import InputText from "primevue/inputtext"
import { defineComponent } from "vue"
export default defineComponent({
name: "FormInput",
emits: ["update:modelValue"],
components: { InputText },
props: {
iconLeft: {
type: String,
default: "",
},
iconRight: {
type: String,
default: "",
},
error: {
type: String,
default: "",
},
label: {
type: String,
default: "",
},
type: {
type: String,
default: "text"
},
modelValue: {
type: String,
required: true
},
},
computed: {
wrapperClass(): any {
return {
"p-float-label": true,
"p-input-icon-left": this.iconLeft,
"p-input-icon-right": this.iconRight,
}
},
},
methods: {
onInput(value: any): any {
this.$emit("update:modelValue", value)
},
},
})
</script>
用法:
<FormInput v-model="data" />
<!-- OR -->
<FormInput :modelValue="data" @update:model-value="data = $event" />
演示:
const app = Vue.createApp({
data() {
return {
text: "default value",
}
},
});
app.component('FormInput', {
emits: ["update:modelValue"],
components: {
'inputtext': primevue.inputtext
},
template: `
<span :class="wrapperClass">
<i :class="iconLeft" v-if="iconLeft" />
<inputtext
:type="type"
:modelValue="modelValue"
@update:model-value="onInput"
></inputtext>
<label for="username">{{ label }}</label>
<i :class="iconRight" v-if="iconRight" />
</span>
`,
props: {
iconLeft: {
type: String,
default: "",
},
iconRight: {
type: String,
default: "",
},
error: {
type: String,
default: "",
},
label: {
type: String,
default: "",
},
type: {
type: String,
default: "text"
},
modelValue: {
type: String,
required: true
},
},
computed: {
wrapperClass() {
return {
"p-float-label": true,
"p-input-icon-left": this.iconLeft,
"p-input-icon-right": this.iconRight,
}
},
},
methods: {
onInput(value) {
this.$emit("update:modelValue", value)
},
},
});
app.mount('#app');
<link href="https://unpkg.com/primevue/resources/themes/saga-blue/theme.css" rel="stylesheet">
<link href="https://unpkg.com/primevue/resources/primevue.min.css" rel="stylesheet">
<link href="https://unpkg.com/primeicons/primeicons.css" rel="stylesheet">
<script src="https://unpkg.com/vue@next"></script>
<script src="https://unpkg.com/primevue/inputtext/inputtext.min.js"></script>
<div id="app">
<form-input v-model="text"></form-input>
<pre>
{{ text }}
</pre>
</div>