Vue:通过方法从父组件提交子组件表单的最佳方式
Vue: Best way to submit form of child component from the parent component through method
我有 2 个组件。
父组件:
Vue.component('parent', {
template: '<div><child :counter="counter" :isSubmit="isSubmit" showButton="true"></child>'+
'<button v-on:click="changeCounter">Change Counter</button></div>',
data () {
return {
counter: 2,
isSubmit : false
}
},
methods : {
changeCounter () {
//retrieve value of counter dynamically let's say through ajax call.
this.counter = 9;
this.isSubmit = true;
}
}
})
子组件:
Vue.component('child', {
template: '<form action="test.php" method="GET" ref="childForm">'+
'<input type="hidden" v-model="counter" name="counter" />'+
'<input type="submit" v-if="showButton" /></form>',
props: {
counter : {
type: Number,
default: 0
},
showButton:false,
isSubmit: false
},
watch : {
isSubmit (val) {
console.log("Inside watcher");
this.submitForm();
}
},
methods : {
submitForm () {
console.log(this.counter);// output-9
this.$refs.childForm.submit();
},
}
})
index.html
....
<div id="app>">
<parent></parent>
<parent></parent>
</div>
....
在这个例子中,当我点击“更改计数器”按钮时,提交的表单带有计数器的旧值(即提交到 /test.php?counter=2)。尽管子组件的道具在开发工具中是反应性的(计数器 = 9),但它在提交表单时不会反映出来。但如果我通过子组件上的提交按钮提交表单(即提交给 /test.php?counter=9),它真的有效。
感谢您的帮助。请帮助我理解为什么会出现这种行为并寻求解决方案。
提前致谢。
速记
由于您使用的是 GET 请求,因此可以跳过整个 <form>
部分,直接转到 URL
methods: {
changeCounter () {
this.counter = 9
window.location = `test.php?counter=${this.counter}`
}
}
更长的答案
您需要等待 counter
更改更新 DOM 才能使用正常的表单提交。
要等待状态更改影响 DOM,请使用 $nextTick
。我还建议通过 submitForm
方法提交表单,而不是查看布尔值。您可以使用 refs.
访问该方法
Vue.component('child', {
template: `<form action="test.php" method="GET" ref="childForm">
<input type="hidden" :value="counter" name="counter" />
<input type="submit" v-if="showButton" />
</form>`,
props: {
counter : {
type: Number,
default: 0
},
showButton: Boolean
},
methods: {
async submitForm () {
await this.$nextTick() // wait for the DOM to update
this.$refs.childForm.submit()
}
}
})
Vue.component("parent", {
template: `<div>
<child :counter="counter" :show-button="true" ref="form"></child>
<button @click="changeCounter">Change Counter</button>
</div>`,
data: () => ({ counter: 2 }),
methods: {
changeCounter () {
this.counter = 9
this.$refs.form.submitForm() // call the child component method
}
}
})
我有 2 个组件。
父组件:
Vue.component('parent', {
template: '<div><child :counter="counter" :isSubmit="isSubmit" showButton="true"></child>'+
'<button v-on:click="changeCounter">Change Counter</button></div>',
data () {
return {
counter: 2,
isSubmit : false
}
},
methods : {
changeCounter () {
//retrieve value of counter dynamically let's say through ajax call.
this.counter = 9;
this.isSubmit = true;
}
}
})
子组件:
Vue.component('child', {
template: '<form action="test.php" method="GET" ref="childForm">'+
'<input type="hidden" v-model="counter" name="counter" />'+
'<input type="submit" v-if="showButton" /></form>',
props: {
counter : {
type: Number,
default: 0
},
showButton:false,
isSubmit: false
},
watch : {
isSubmit (val) {
console.log("Inside watcher");
this.submitForm();
}
},
methods : {
submitForm () {
console.log(this.counter);// output-9
this.$refs.childForm.submit();
},
}
})
index.html
....
<div id="app>">
<parent></parent>
<parent></parent>
</div>
....
在这个例子中,当我点击“更改计数器”按钮时,提交的表单带有计数器的旧值(即提交到 /test.php?counter=2)。尽管子组件的道具在开发工具中是反应性的(计数器 = 9),但它在提交表单时不会反映出来。但如果我通过子组件上的提交按钮提交表单(即提交给 /test.php?counter=9),它真的有效。
感谢您的帮助。请帮助我理解为什么会出现这种行为并寻求解决方案。
提前致谢。
速记
由于您使用的是 GET 请求,因此可以跳过整个 <form>
部分,直接转到 URL
methods: {
changeCounter () {
this.counter = 9
window.location = `test.php?counter=${this.counter}`
}
}
更长的答案
您需要等待 counter
更改更新 DOM 才能使用正常的表单提交。
要等待状态更改影响 DOM,请使用 $nextTick
。我还建议通过 submitForm
方法提交表单,而不是查看布尔值。您可以使用 refs.
Vue.component('child', {
template: `<form action="test.php" method="GET" ref="childForm">
<input type="hidden" :value="counter" name="counter" />
<input type="submit" v-if="showButton" />
</form>`,
props: {
counter : {
type: Number,
default: 0
},
showButton: Boolean
},
methods: {
async submitForm () {
await this.$nextTick() // wait for the DOM to update
this.$refs.childForm.submit()
}
}
})
Vue.component("parent", {
template: `<div>
<child :counter="counter" :show-button="true" ref="form"></child>
<button @click="changeCounter">Change Counter</button>
</div>`,
data: () => ({ counter: 2 }),
methods: {
changeCounter () {
this.counter = 9
this.$refs.form.submitForm() // call the child component method
}
}
})