Vue:在另一个页面上显示来自表单提交的响应

Posted

技术标签:

【中文标题】Vue:在另一个页面上显示来自表单提交的响应【英文标题】:Vue: display response from form submit on another page 【发布时间】:2020-09-11 06:38:54 【问题描述】:

我在vue 中有一个<form>。我将该表单发送到服务器,获取 JSON 响应,然后将其打印到控制台。它工作正常。

但是,我需要获取该 JSON 响应并将其显示在另一个页面上。例如,我有两个 .vue 文件:GetAnimal.vue 具有表单并从 API 检索动物数据,DisplayAnimal.vue 显示动物数据。我需要将响应动物数据从GetAnimal.vue 定向到DisplayAnimal.vue

GetAnimal.vue

<template>
 <form v-on:submit.prevent="getAnimal()">
  <textarea v-model = "animal"
      name = "animal" type="animal" id = "animal"
      placeholder="Enter your animal here">
  </textarea>

  <button class = "custom-button dark-button"
      type="submit">Get animal</button>
 </form>
</template>
<script>
    import axios from 'axios';

    export default 
        name: 'App',
        data: function() 
            return 
                info: '',
                animal: ''
            
        ,
        methods:  
            getAnimal: function()  
                 axios
                    .get('http://localhost:8088/animalsapi?animal=' + this.animal)
                    .then(response => (this.info = response.data));
                 console.log(this.info);
            
        
    
</script>

回复: 检索带有动物数据的 JSON,如下所示:


"fur-color": "yellow",
"population": 51000,
"isExtinct": false,
"isDomesticated": true

我现在想将该 JSON 提供给位于 /viewanimal 端点的 DisplayAnimal.vue

DisplayAnimal.vue

<template>
  <div>
    <p>Animal name: animal</p>
    <p>Fur color: furColor</p>
    <p>Population: population</p>
    <p>Is extinct: isExtinct</p>
    <p>Is domesticated: isDomesticated</p>
  </div>
</template>

我该怎么做?我知道我可以通过this.$router.push( path ); 重定向,但我只将它用于导航,而这里需要传递 JSON 响应。这甚至是解决此问题的正确/良好做法吗?

编辑

我试过了:

GetAnimal.vue 我添加了这个数据:

data: function() 
   return 
     animal:  
       name: 'Cat',
       furColor: 'red',
       population: '10000',
       isExtinct: false,
       isDomesticated: true

DisplayAnimal.vue 中:

<script>
    export default  
        props:  
            animal:  
                name: 
                    type: String
                ,
                furColor:  
                    type: String
                ,
                population: String,
                isExtinct: String,
                isDomesticated: String
            
        
    

</script>

GetAnimal.vue 我添加了这个:

methods: 
            animals: function()  
                alert("animals");
                this.$router.push(name: 'viewanimal',
                                query: animal: JSON.stringify(this.animal));
            ,

尝试使用显示组件显示该测试动物。但是它不起作用 - 我得到一个空页面。

【问题讨论】:

像这样保存数据的正确方法是使用 Vuex 状态 为什么不$router.push 将表单输入(作为查询)到接收组件并在那里调用 API?否则,我必须同意这里的其他人,这最好用 Vuex 来完成。 如果您想要快速解决方案,您可以localStorage.setItem("animal", JSON.stringify(yourdata)); 然后您可以使用var data = JSON.parse(localStorage.getItem("animal")); 检索,最后使用localStorage.removeItem("animal"); 删除它,您可以在developer.mozilla.org/en-US/docs/Web/API/Window/localStorage 阅读有关localStorage 的信息。正确的解决方案是您开始使用 vuex,然后您可以轻松地在路由器组件之间共享数据,vuex 可能听起来很吓人,但这是您在 SPA 中获得的最佳选择。 @mentorgashi 它如何同时工作?有几个用户同时用不同的动物填写表格并想查看他们动物的数据? localStorage 不是作为全局/静态变量工作,只有 1 个副本/值在各处共享吗? 你可以从这里开始 vuex 的基础知识 vuemastery.com/courses/mastering-vuex/… 非常好的和透彻的解释。 【参考方案1】:

首先创建一个名为 services 的第二个文件夹,并为您的 axios 调用创建 service.js - 良好的实践和更简洁的代码。 第二次使用vuex。这种数据最好配合vuex使用。

据我了解 GetAnimal.vue 是父组件,您希望在子组件 DisplayAnimal.vue 中显示它。 如果是这样,你想看看这是否有效,只需使用道具。 您还可以使用 $emit() 将孩子的相同信息或任何其他信息发送回父母。 强烈建议使用 vuex 来管理状态

【讨论】:

你能显示一些代码吗?不,GetAnimal.vue 目前与DisplayAnimal.vue 没有任何关联——我拥有的代码就是我发布的代码。为什么会是父母?我正在考虑 GetAnimal.vue 既是控制器又是模型的 MVC 模型:表单获取用户的输入并更新模型(动物信息:this.info)。现在只需将该信息传递给视图 DisplayAnimal.vue 我来自 Java,在 Java 应用程序中我没有看到扩展模型/控制类的视图类 - 这种关系通常是一种组合而不是继承。 那你想做什么?为了在 vue 中显示从一个组件到另一个组件的数据,使用 vuex 或使用 props 传递数据(从父级到子级,或者您可以将其称为兄弟姐妹),即使使用道具也是如此。【参考方案2】:
Vue.component('product',
  props:
    message:
      type:String,
      required:true,
      default:'Hi.'
    
  ,
  template:`<div>message</div>`,
  data()...
)

//html in the other component you axios call is in this component //<product meesage="hello"></product>

【讨论】:

您在 vuejs 中总共有 3 个选项,这取决于您的需要 1-使用道具从父级到子级共享数据,2-发出自定义事件以从子级到父级共享数据,3 - 使用 Vuex 创建应用级共享状态。 我如何将message 值传递给该组件?我已经阅读过关于 props 的内容,但我不明白如何将 props 值从 GetAnimal.vue 分配给 DisplayAnimal.vue 您写“props”的组件是接收组件,如上所示,您通过 v-bind Vue.component('storage', data: return message= 从另一个组件发送它,//说它通过 axios 调用获取数据 ,.... ) 当你想显示它时你想告诉同一个产品组件它s about to get some props &lt;template&gt; //你也可以使用简写 :message="message" ` 存储告诉产品组件它发送带有消息名称的消息道具,并在产品组件内部指定道具 先学基础再学 vuex 状态。 data() return ... 发现一个错字【参考方案3】:

我会将动物名称/id 作为路由参数传递给显示页面,并让该组件负责获取和显示相关的动物数据。这样就避免了用户可以直接通过 URL 访问显示页面并看到一个不完整的页面的情况。

在您希望在页面之间共享本地状态的情况下,正如其他人指出的那样,您可能希望使用Vuex。

编辑:

我正在按照 OP 的要求在我的答案中添加一些代码。

路线:

const routes = [
   path: "/", component: SearchAnimals ,
   path: "/viewanimal/:name", component: DisplayAnimal, name: "displayAnimal" 
];

DisplayAnimal.vue:

<template>
  <div>
    <p>Animal name: animal.name</p>
    <p>Fur color: animal.furColor</p>
    <p>Population: animal.population</p>
    <p>Is extinct: animal.isExtinct</p>
    <p>Is domesticated: animal.isDomesticated</p>
  </div>
</template>

<script>
import axios from "axios";

export default 
  name: "DisplayAnimal",
  data: () => (
    animal: 
  ),
  methods: 
    fetchAnimal(name) 
      axios
        .get(`http://localhost:8088/animalsapi?animal=$name`)
        .then(response => 
          this.animal = response.data;
        );
    
  ,
  created() 
    this.fetchAnimal(this.$route.params.name);
  
;
</script>

SearchAnimals.vue:

<template>
  <form v-on:submit.prevent="onSubmit">
    <textarea
      v-model="animal"
      name="animal"
      type="animal"
      id="animal"
      placeholder="Enter your animal here"
    ></textarea>
    <button type="submit">Get animal</button>
  </form>
</template>

<script>
export default 
  name: "SearchAnimal",
  data: () => (
    animal: ""
  ),
  methods: 
    onSubmit() 
      this.$router.push(
        name: "displayAnimal",
        params:  name: this.animal 
      );
    
  
;
</script>

显然这是一个简单的示例,因此不包含任何错误处理等,但它应该可以让您启动并运行。

【讨论】:

我真的不想这样限制自己 - 也许以后我想通过用户提供的毛皮颜色来获得动物:fur color -&gt; form -&gt; server -&gt; returns animal -&gt; DisplayAnimal.vue -&gt; displaying the animal 而您的解决方案需要fur color -&gt; form -&gt; server -&gt; returns animal with that fur color -&gt; pass animal name to DisplayAnimal.vue -&gt; server -&gt; returns animal with that name -&gt; displaying the animal 我可以看到我最好的选择是将数据作为 HTTP 参数传递给DisplayAnimal.vue。我在考虑可能将数据作为 POST 参数传递:animal name/fur/whatever -&gt; form -&gt; server -&gt; returns animal -&gt; GetAnimal.vue creates a POST request with JSON animal as a request parameter -&gt; redirects to the DisplayAnimal.vue with the POST JSON animal parameter being passed to the GetAnimal.vue。有可能吗? 我想这取决于你想要达到的目标。鉴于您刚才所说,为什么要将动物展示视为单独的路线?查询 API 并在同一路径中显示返回的动物数据似乎更有意义。 但为此我必须摆脱我已经拥有的元素 - 接受用户输入的表单。如果我以后想在其他地方展示动物怎么办?我必须重复显示代码?您将如何在同一页面中执行此操作?以某种方式删除表单元素并将其替换为显示动物数据的 div?如果该页面上有很多元素要删除怎么办? 嗯,这一切都取决于你的页面布局。你可以换掉组件,用结果替换表单,或者你选择在表单旁边显示数据(可能更好的 UI)。如果显示代码是一个接收动物作为道具的组件,那么在其他地方重用它很简单。【参考方案4】:

使用Vuex,你可以轻松解决这个问题

netlify 上的工作示例 https://m-animalfarm.netlify.app/

github上的代码 https://github.com/manojkmishra/animalfarm

GetAnimal.vue(我已禁用 axios 调用以进行测试和硬编码信息)

 <template>
 <form v-on:submit.prevent="getAnimal()">
   <textarea v-model = "animal" name = "animal" type="animal" id = "animal"
   placeholder="Enter your animal here">
  </textarea>
  <button class = "custom-button dark-button"
  type="submit">Get animal</button>
  </form>
 </template>
 <script>
 import axios from 'axios';
 export default 
 
    name: 'App',
    data: function()   return  info: '', animal: ''    ,
    methods:  
        getAnimal: function()  
            // axios
            //   .get('http://localhost:8088/animalsapi?animal=' + this.animal)
             //   .then(response => (this.info = response.data),
                this.info="fur-color": "yellow","population": 51000,"isExtinct":     
                            false,"isDomesticated": true ,
                this.$store.dispatch('storeAnimals', this.info)
                //);
        
    
 
 </script>

DisplayAnimal.vue

<template>
<div>
<p>Animal name: stateAnimal.animal</p>
<p>Fur color: stateAnimal.furColor</p>
<p>Population: stateAnimal.population</p>
<p>Is extinct: stateAnimal.isExtinct</p>
<p>Is domesticated: stateAnimal.isDomesticated</p>
 </div>
</template>
<script>
 import mapState, mapGetters from 'vuex';
export default 
computed:  ...mapState( stateAnimal:state => state.modulename.stateAnimal ),   
 ,

</script>

modulename.js(存储模块)

export default

 state: stateAnimal:null,  ,
 getters: ,
 mutations: 
     ['STORE_ANIMALS'] (state, payload) 
      state.stateAnimal = payload;  
    console.log('state=',state)
   ,

  ,
 actions: 
   storeAnimals: (commit, data) => 
     console.log('storeanim-data-',data);
      commit(  'STORE_ANIMALS', data   );  
    ,     
  
  

Index.js(用于 vuex 存储),如果页面刷新,您可以禁用持久状态作为保存状态

import Vue from 'vue'
import Vuex from 'vuex'
import modulename from './modules/modulename'
import createPersistedState from "vuex-persistedstate";

Vue.use(Vuex)
export default new Vuex.Store(
plugins: [createPersistedState( storage: sessionStorage )],
state:   ,
mutations:   ,
actions:   ,
modules:  modulename 
)

所有组件的状态都可用/共享

【讨论】:

感谢您的回答。我应该运行modulename.jsindex.js 吗?或者我应该如何处理这些文件?另外,$store.storeAnimals 变量是全局变量吗?正如您所说,所有组件都可以访问它。如果我在两个不同的页面上有两个表单,同一用户同时用不同的动物填写这些表单怎么办 - 这些表单应该指向将显示两种动物的 DisplayAnimal.vue 页面 - 但如果动物存储在全局变量中,它会被覆盖,所以本质上会展示相同的动物——最后写入商店的那个? Vuex store 包含在路由器等 vue 项目的 main.js 中。我已删除模块并将所有 vuex 代码包含在 github repo 上 store 文件夹的 index.js 中。是的 vuex 状态变量是全局的。你是对的——如果你将两种形式的东西存储在同一个状态变量中,它将更新为最新值。但是您可以将来自 diff 表单的值存储在 diff 状态变量中,以防您希望它们分开并且它们都将在全局范围内可用。 但是DisplayAnimal.vue 不是只查看$store 中的单个变量来显示吗?如果我要同时打开未知数量的表格怎么办?我必须为每个变量创建一个单独的变量吗?我真的很抱歉这么说,但这对我来说似乎不是一个可行的解决方案。 我来自 Java,这非常简单地完成了 - 没有任何全局变量 - .jsp.html 页面查看了 HttpRequest 对象并从中获取attributeattribute 是与该特定请求相关联的一条数据。所以服务器只会将 JSON 附加到请求中:request.setAttribute("animal", animalJsonString);,页面将&lt;p&gt;request.get("animal")&lt;/p&gt; 那是伪代码,但你明白了要点。在我看来,vue 似乎没有这样的属性?但我认为vuex 的工作方式类似——但事实并非如此——我心中的全局状态是针对不同的事物、应用程序特定的事物:比如整个应用程序只有一个动物等等——不是特定于请求的数据片段 - 所以看起来我使用 vue 的唯一选择是将动物 JSON 数据作为 GETPOST 参数传递。看到GET参数的长度是有限的,那就是POST参数。

以上是关于Vue:在另一个页面上显示来自表单提交的响应的主要内容,如果未能解决你的问题,请参考以下文章

在同一页面上显示提交的表单响应。 (没有重装)

在goahead中如何实现在一个页面提交表单数据,在另一个页面获取表单提交过来的数据

html中提交表单后如何在同一页面上显示表格?

表单提交后,我需要显示一条包含变量(来自表单的答案)的消息

关于提交表单页面无响应

使用无显示按钮防止在 Jquery 表单提交上加载页面