Vue.js 3:如何使用道具预填充绑定表单
Vue.js 3: how to pre-populate bound form with props
我正在尝试使用 Vuejs 3 创建一个简单的 CRUD 应用程序。
我的主页有一个表单(作为子组件)和一个 table 包含创建的项目(作为另一个子组件)。我通过表单向 API/database 和 table 更新提交数据。到目前为止一切顺利。
然后,对于更新阶段,我希望每个项目都有一个详细信息页面,我也会在其中包含表单(重复使用相同的组件)。但想法是表单字段将预先填充来自 API/Database.
的数据
主页上的 table 有一个 route-link
到详细信息页面,我将项目的 id
作为 params
传递。详细信息页面根据 id
向 API 发出请求,接收项目数据并将它们作为 props
传递到表单组件中。
如果我尝试像这样将数据直接渲染到模板中,它工作正常:
<p v-if="submitType === 'update' && item.id">{{ item.id }}</p>
现在,表单字段由 v-model
绑定到 data
(例如 form.id
)。但是当我尝试如下重新填充它时,我总是得到未定义的值。
data() {
return {
form: {
id: this.submitType === 'update' ? this.item.id : 0,
}
}
},
我怀疑问题是对 API 的父调用是异步的并且 props
的传递被延迟了。因为当我作为 props
传递一些硬编码值时,它在表单字段中显示为一个值没有问题。此外,如果仅在收到 props
时显示表单(使用 v-if
指令),则 data.form.id
仍未定义。
那么有没有什么方法可以用接收到的 props 预填充绑定的表单字段,并且仍然让表单组件重用于插入和更新操作?其余相关代码如下。非常感谢您
// Detail Page
<template>
<Form :item="item" submit-type="update"></Form>
</template>
<script>
export default {
data() {
return {
item: {}
}
},
created() {
callAPI(id).then( response => this.item = response.data )
}
}
</script>
// Form Component
<template>
<p v-if="submitType === 'update' && item.id">{{ item.id }}</p>
<div v-if="submitType === 'insert' || (submitType === 'update' && item.id )">
<section>
<form @submit.prevent="onSubmit">
<div>
<label for="id">ID</label>
<input id="id" name="id" v-model="form.id" type="number" placeholder="ID">
</div>
<input type="submit" value="Save">
</form>
</section>
</div>
</template>
<script>
export default {
name: 'Form',
props: {
item: {
type: Object
},
submitType: {
type: String
}
},
data() {
return {
form: {
id: this.submitType === 'update' ? this.item.id : 0,
}
}
},
}
</script>
你可以试试watchers,看看下面的代码片段:
const app = Vue.createApp({
data() {
return {
item: {},
type: 'update'
}
},
methods: {
change() {
this.type === 'update' ? this.type = 'insert' : this.type = 'update'
}
},
created() {
fetch('https://jsonplaceholder.typicode.com/todos/1')
.then(response => response.json())
.then(json => this.item = json)
//callAPI(id).then( response => this.item = response.data )
}
})
app.component('myForm', {
template: `
<p v-if="submitType === 'update' && item.id">{{ item.id }}</p>
<div v-if="submitType === 'insert' || (submitType === 'update' && item.id )">
<section>
<form @submit.prevent="onSubmit">
<div>
<label for="id">ID</label>
<input id="id" name="id" v-model="form.id" type="number" placeholder="ID">
</div>
<input type="submit" value="Save">
</form>
</section>
</div>
`,
props: {
item: {
type: Object
},
submitType: {
type: String
}
},
data() {
return {
form: {}
}
},
methods: {
fillData() {
this.submitType === 'update' ? this.form = {...this.item} : this.form = {id: 0}
}
},
watch: {
item() {
this.fillData()
},
submitType() {
this.fillData()
}
},
})
app.mount('#demo')
<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
<div id="demo">
<button @click="change">switch type</button>
{{type}}
<my-form :item="item" :submit-type="type"></my-form>
</div>
我正在尝试使用 Vuejs 3 创建一个简单的 CRUD 应用程序。
我的主页有一个表单(作为子组件)和一个 table 包含创建的项目(作为另一个子组件)。我通过表单向 API/database 和 table 更新提交数据。到目前为止一切顺利。
然后,对于更新阶段,我希望每个项目都有一个详细信息页面,我也会在其中包含表单(重复使用相同的组件)。但想法是表单字段将预先填充来自 API/Database.
的数据主页上的 table 有一个 route-link
到详细信息页面,我将项目的 id
作为 params
传递。详细信息页面根据 id
向 API 发出请求,接收项目数据并将它们作为 props
传递到表单组件中。
如果我尝试像这样将数据直接渲染到模板中,它工作正常:
<p v-if="submitType === 'update' && item.id">{{ item.id }}</p>
现在,表单字段由 v-model
绑定到 data
(例如 form.id
)。但是当我尝试如下重新填充它时,我总是得到未定义的值。
data() {
return {
form: {
id: this.submitType === 'update' ? this.item.id : 0,
}
}
},
我怀疑问题是对 API 的父调用是异步的并且 props
的传递被延迟了。因为当我作为 props
传递一些硬编码值时,它在表单字段中显示为一个值没有问题。此外,如果仅在收到 props
时显示表单(使用 v-if
指令),则 data.form.id
仍未定义。
那么有没有什么方法可以用接收到的 props 预填充绑定的表单字段,并且仍然让表单组件重用于插入和更新操作?其余相关代码如下。非常感谢您
// Detail Page
<template>
<Form :item="item" submit-type="update"></Form>
</template>
<script>
export default {
data() {
return {
item: {}
}
},
created() {
callAPI(id).then( response => this.item = response.data )
}
}
</script>
// Form Component
<template>
<p v-if="submitType === 'update' && item.id">{{ item.id }}</p>
<div v-if="submitType === 'insert' || (submitType === 'update' && item.id )">
<section>
<form @submit.prevent="onSubmit">
<div>
<label for="id">ID</label>
<input id="id" name="id" v-model="form.id" type="number" placeholder="ID">
</div>
<input type="submit" value="Save">
</form>
</section>
</div>
</template>
<script>
export default {
name: 'Form',
props: {
item: {
type: Object
},
submitType: {
type: String
}
},
data() {
return {
form: {
id: this.submitType === 'update' ? this.item.id : 0,
}
}
},
}
</script>
你可以试试watchers,看看下面的代码片段:
const app = Vue.createApp({
data() {
return {
item: {},
type: 'update'
}
},
methods: {
change() {
this.type === 'update' ? this.type = 'insert' : this.type = 'update'
}
},
created() {
fetch('https://jsonplaceholder.typicode.com/todos/1')
.then(response => response.json())
.then(json => this.item = json)
//callAPI(id).then( response => this.item = response.data )
}
})
app.component('myForm', {
template: `
<p v-if="submitType === 'update' && item.id">{{ item.id }}</p>
<div v-if="submitType === 'insert' || (submitType === 'update' && item.id )">
<section>
<form @submit.prevent="onSubmit">
<div>
<label for="id">ID</label>
<input id="id" name="id" v-model="form.id" type="number" placeholder="ID">
</div>
<input type="submit" value="Save">
</form>
</section>
</div>
`,
props: {
item: {
type: Object
},
submitType: {
type: String
}
},
data() {
return {
form: {}
}
},
methods: {
fillData() {
this.submitType === 'update' ? this.form = {...this.item} : this.form = {id: 0}
}
},
watch: {
item() {
this.fillData()
},
submitType() {
this.fillData()
}
},
})
app.mount('#demo')
<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
<div id="demo">
<button @click="change">switch type</button>
{{type}}
<my-form :item="item" :submit-type="type"></my-form>
</div>