javascript - Tại sao Input không lưu dữ liệu đã nhập trong Prop modelValue
Tôi đã đọc vài bài đăng về Vue 3 liên quan đến v-model và :value. Nhưng không bài nào thực sự giúp tôi trong trường hợp này.
Tôi muốn lưu giá trị trong prop modelValue và muốn cập nhật nó mỗi khi nó được người dùng nhập hoặc thay đổi.
Mã này chạy mà không có lỗi nào nhưng hiển thị modelValue: undefined trong bảng điều khiển phát triển Vue 3.
Mã Vue của tôi:
<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>
Thành phần cha:
<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>
Vui lòng xem ảnh chụp màn hình này
Thành phần cha trong Bảng điều khiển Dev
Câu trả lời #1
Có một vài việc cần phải sửa:
Thành phần PrimeVue
InputTextkhông có propvaluemà cómodelValue(để hỗ trợv-model) - Tài liệu InputText + đọc Sử dụng v-model trên Components để tìm hiểu sự khác biệt giữav-modeltrên input gốc và các thành phần tùy chỉnhInputTextkhông phải là một phần tửinputgốc, vì vậy không có lý do để lắng nghe sự kiệninput. Thành phần đang phát ra sự kiệnupdate:modelValue. Ngoài ra dữ liệu của sự kiện không phải là sự kiện gốc nênevent.target.valuekhông có ý nghĩa, chỉ cần sử dụngvalue- nguồnViệc nhân đôi
p-filledlà không cần thiết vìInputTextđã làm điều này rồi (xem nguồn ở trên)
// 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>
Cách sử dụng :
<FormInput v-model="data" />
<!-- OR -->
<FormInput :modelValue="data" @update:model-value="data = $event" />
Trình diễn :
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>
