vue 提交带有更新输入值的表单

问题描述

我有一个简单的隐藏表单

<template>
  <form ref="form" method="POST" action="https://target.com/post" accept-charset="utf-8">
    <input type="hidden" name="data" :value="myData"/>
    <input type="hidden" name="signature" v-model="mySignature" />
    <input ref="submit" type="submit">
  </form>
</template>

并且我希望附加到不同按钮 (v-on:click="submitForm") 的方法提交此表单设置数据。

export default {
  name: 'MyComponent',methods: {
    submitForm() {
      // should update values for inputs
      this.myData = 'dynamically calculated';
      this.mySignature = 'creates signature from data';
      // submit the form with values above
      this.$refs.form.submit();
    },},data() {
    return {
      myData: null,mySignature: null,}
  }
}

但似乎我误解了 Vue 中的 reactivity/binding/refs?,所以我尝试过

  • this.$refs.submit.click();
  • this.$forceUpdate();
  • 在输入上设置 :value="myData"/ v-model="myData"

并且没有一种方法有效。表单发送时带有 data/signature 的空字段,因此变量似乎未更新或表单无法在一次函数调用中重新呈现。进行此类更新的正确方法是什么?

解决方法

Vue 异步执行 DOM 更新。 在您的情况下,DOM 更新不会在表单提交之前发生。

解决方法是使用 $nextTick

this.$nextTick(() => {
    this.$refs.form.submit();
});
,

看起来是 <form> 的问题,而不是反应性。

您已经定义了一个带有操作 <form>action="https://target.com/post" 元素。这会告诉浏览器处理您的表单并忽略任何 javascript 处理。当用户点击 <input ref="submit" type="submit">

如果您正在构建 SPA,您可能应该删除表单元素并使用 ajax 调用处理提交。这将使表单交互的处理更加一致,但您将失去不启用 js 的回退功能,但是,鉴于它是由 js 触发的隐藏表单,无论如何这可能不是问题。

无论如何,如果你想用一个 form 元素来处理它,你可以添加一个 @submit 事件处理程序,在处理程序中带有一个 e.preventDefault() 以防止表单在条件满足时提交不匹配。请务必在多个浏览器上进行测试,因为 chrome 和 firefox 之间在处理表单提交功能方面存在一些不一致。

<template>
  <form ref="form" method="POST" action="https://target.com/post" accept-charset="utf-8" @submit="handleSubmitForm">
    <input type="hidden" name="data" :value="myData"/>
    <input type="hidden" name="signature" v-model="mySignature" />
    <input ref="submit" type="submit">
  </form>
</template>
export default {
  name: 'MyComponent',methods: {
    submitForm() {
      // should update values for inputs
      this.myData = 'dynamically calculated';
      this.mySignature = 'creates signature from data';
      // submit the form with values above
      this.$refs.form.submit();
    },handleSubmitForm(e) {
      if (this.myData !== "what I want") {
        e.preventDefault();  // prevent form submit
      }
    },},data() {
    return {
      myData: null,mySignature: null,}
  }
}
,

我遇到了同样的问题,并找到了以下解决方案:

this.myData = 'dynamically calculated';
this.mySignature = 'creates signature from data';

//force to update form
this.$refs.form.data = this.myData;
this.$refs.form.signature = this.mySignature;

// submit the form with values above
this.$refs.form.submit();

但是,nextTick 方法更好。