【问题标题】:Avoid new axios request each time vue component is rendered每次渲染 vue 组件时避免新的 axios 请求
【发布时间】:2019-04-20 04:12:52
【问题描述】:

我对 Vue 非常陌生,所以请原谅我在这里缺乏知识。

  1. 在我的一个(子)组件(Product_Collection.vue) 中,我提出了一个 axios 请求,通过他们的 GraphQL API 从我的 Shopify 商店获取一些产品:

    data: () => {
     return {
       products: null
     }
    },
    methods: {
     getProducts: function(){
       // 1. axios code here...
       // 2. ...then assign result to "this.products" data property 
     }
    }
    
  2. 产品显示为缩略图(假设有 10 件 T 恤)。然后,我单击产品以查看更多详细信息以及更多产品信息和图像等(非常类似于亚马逊的体验)。

  3. 产品在Product_Single.vue 组件中单独显示。到目前为止一切顺利。

但问题来了……

  1. 当我点击返回产品页面 (Product_Collection.vue)(上面有 10 件 T 恤的页面)时,再次调用 Shopify API 的 axios 请求,并且从头开始重新渲染组件。

我的问题是如何告诉 Vue 在每次渲染组件时停止从 Shopify API 获取数据?谢谢

【问题讨论】:

  • 您可以使用vuex 存储数据以检查数据是否可用。仅在未拉取数据时请求获取数据。 vuex.vuejs.org/guide
  • 这似乎是个好主意,毫无疑问它会起作用,但对于这样一个简单的问题,它似乎有点过于复杂。我考虑在组件上使用<keep-alive>,因为这听起来像是为这种类型的场景设计的,但它并没有像我预期的那样工作 - 老实说我可能没有正确使用它或者我误解了它目的。

标签: javascript vue.js axios shopify vue-component


【解决方案1】:

听起来你想要缓存控制,Axios 通过扩展支持它。

https://github.com/kuitos/axios-extensions

import axios from 'axios';
import { cacheAdapterEnhancer } from 'axios-extensions';

const http = axios.create({
    baseURL: '/',
    headers: { 'Cache-Control': 'no-cache' },
    // cache will be enabled by default
    adapter: cacheAdapterEnhancer(axios.defaults.adapter)
});

http.get('/users'); // make real http request
http.get('/users'); // use the response from the cache of previous request, without real http request made
http.get('/users', { cache: false }); // disable cache manually and the the real http request invoked

或者您可以走更复杂的路线并将结果自己缓存到一个对象中,并检查该对象是否存在,但是您必须处理何时要使该对象中的数据过期。

如果您使用缓存控制、缓存控制标头和过期,您可以从 API 层驱动所有这些,而不必在应用程序中处理手动管理的陈旧数据。

【讨论】:

  • 这看起来很有希望。它似乎非常适合我的特定场景,我相信它会按照我的需要工作,但我不禁想到,由于我缺乏 Vue 经验,我错过了一些更明显的关于为什么组件拉动的东西每次都从 API 中获取数据,而不是仅仅重用上一次渲染中的数据。也许我需要更多地使用computedwatch 教育自己,看看它们是否可以在这里使用。谢谢
  • 即使启用了缓存,如果您监控您的流量,它看起来像是在调用,但实际上它是从缓存中获取的。您可以使用 MITM 代理来验证这一点。
  • 啊,这很有趣——所以你是说它当前可能正在从缓存中获取,而不是每次都执行一个新的 HTTP 请求?我正在使用 Chrome DevTools(网络选项卡)来监控对 Shopify 服务器的 API 调用,它每次都显示看起来像一个新的(非缓存)请求,但是我如何检查响应的位置 实际 来自?我不熟悉 MITM 代理; Chrome DevTools 不能做类似的事情吗?谢谢
  • 是的,您也可以在 Chrome DevTools 中查看信息。转到网络选项卡,单击您感兴趣的呼叫并查找Status Code: 200 (from disk cache)。如果没有说(from disk cache),请检查您的cache-control maxage
  • 我不知道Status Code: 200 (from disk cache) 的事情。这是非常有用的信息,谢谢。我还在 DevTools 中选择了 Disable cache,这导致在 每个 POST 请求之前发送预检 OPTIONS 请求方法。取消选择 Disable cache 后,OPTIONS 请求方法将停止发送,并且仅记录了 POST 请求方法。
【解决方案2】:

如果你没有使用 Vue Router,并且隐藏了列表页面,你可以尝试一个简单的选项。

使用 v-show 代替 v-if。该组件将被隐藏并再次显示。它不会被重新创建。

另外,您在哪里调用 API?来自createdmounted 钩子?

【讨论】:

  • 不幸的是,我正在使用 Vue 路由器。尽管我确实喜欢使用 v-ifv-show 显示/隐藏组件的想法,所以也许我会重新考虑使用 Vue Router 并仅使用条件逻辑来显示内容。我从 created 钩子 btw 调用 API
  • VueRouter 确实尝试为相同的路由重用相同的组件。所以,你可以检查你正在加载哪个钩子......
  • 我确实想知道这一点——我认为 Vue Router 肯定足够聪明,知道这个组件刚刚被显示,因此只需从缓存中提取它。也许是因为我将 products 数据属性设置为 null 并因此基本上强制它重新加载?
  • 是的。应该是这样的。 (即使路由查询参数发生变化,Vue Router 也使用相同的组件,通常,我必须“观察”道具以对变化做出反应。)
  • @BenClarke 你能解决这个问题吗?我遇到了类似的问题,甚至将“已创建”切换为“已安装”,当我导航回主页时,我发现我的组件(如您的产品)正在重新加载。
【解决方案3】:

如果您使用的是 GraphQL,那么 Apollo 状态管理方式可以很好地与 graphQL 集成。看看这个:https://dev.to/n_tepluhina/apollo-state-management-in-vue-application-8k0

所以与其用 axios 重写应用程序并在混合中添加 vuex,也许 Apollo 客户端会更方便

【讨论】:

    猜你喜欢
    • 2020-03-25
    • 2020-05-09
    • 1970-01-01
    • 2018-12-24
    • 2021-08-19
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    • 2022-06-29
    相关资源
    最近更新 更多