How to get data from an API only once (on app creation, outside component or view) in Vue3 SPA, with Pinia store

huangapple go评论59阅读模式
英文:

How to get data from an API only once (on app creation, outside component or view) in Vue3 SPA, with Pinia store

问题

在路由视图加载或组件挂载时避免每次都从API获取数据是否可行且是否是良好的做法?

问题在于某些数据很少更改(比如下拉选项列表,比如我的应用程序中允许的动物选择),每次都向服务器发送请求并不合理,而是在应用程序创建时就足够了。

在App.vue中尝试过,这是常见的做法吗?

在App.vue中:

import { computed, onMounted, onUpdated, ref } from 'vue';
onMounted(() => {
  axios.get('/data')
    .then((res) => {
      store.property = res.data
      // ...
    });
})
英文:

Is it possible and is it a good practice to avoid fetching data from an API every time the router view is loaded or the component is Mounted?

The thing is that some data rarely changes (like a dropdown options list, imagine allowed animal picks for my app) and it's logical not to send a request every time to a server, instead on app creation would be sufficient.

Tried in App.vue, is that a common thing?

IN APP.vue

import { computed, onMounted, onUpdated, ref } from 'vue';
onMounted(()=>{
axios.get('/data')....

.then((res)=>{
store.property = res.data
...
})

})

答案1

得分: 2

我认为将它放在App.vue组件中的挂载是可接受的,因为App组件不会重新挂载。

然而,理想的设置取决于一些其他参数,如应用程序的大小和维护它的团队的大小。在大型应用程序中,您可能希望以更有结构和一致的方式组织事物,以便您和其他人在代码上的工作知道在哪里找到事物。

您可以考虑将API调用移动到pinia动作中。

store.loadMyData()

// 而不是

axios.get('/data')
  .then((res) => {
    store.property = res.data;
  })

这样,您在组件中就会有更少的代码行。拥有“精简”的组件并将“业务逻辑”移出组件通常会使组织更好,从而更容易维护。

在动作中,您可以跟踪API的状态

const STATES = {
  INIT: 0,
  DONE: 1,
  WIP: 2,
  ERROR: 3
}
export const useMyApiStore = defineStore('myapi', {
  state: () => ({
    faves: [],
    favesState: STATES.INIT
  }),
  actions: {
    loadMyData() {
      this.store.favesState = STATES.WIP;
      axios.get('/data')
        .then((res) => {
          this.store.property = res.data;
          this.store.favesState = STATES.DONE;
        })
        .catch((e) => {
          this.store.favesState = STATES.ERROR;
        })
    },
  },
  getters: {
    isLoaded(){
      return this.store.favesState === STATES.DONE;
    }
    isLoading(){
      return this.store.favesState === STATES.WIP;
    }
  }
})

这显然更冗长,但允许组件更小,包含更少的逻辑。然后,例如,在您的组件中,您可以使用getter isLoading 来显示加载指示器,或者在另一个组件中使用 isLoaded 来确定是否显示它。

英文:

I think having it on mount in the App.vue component is acceptable since the App component would not be remounted.

The ideal setup, however, depends on some other parameters like size of application and size of team that's maintaining it. In a large applications you might want to organize things in amore structured and consistent way so you and other folks working on the code know where to find things.

You could consider moving the API call into the pinia action.

store.loadMyData()

// instead of

axios.get('/data')
  .then((res)=>{
    store.property = res.data;
  })

That way you have fewer lines of code in the component. Having "lean" components and moving "business logic" out of components usually makes for better organization which makes it easier to maintain.

Within the action, you can track the state of the API

const STATES = {
  INIT: 0,
  DONE: 1,
  WIP: 2,
  ERROR: 3
}
export const useMyApiStore = defineStore('myapi', {
  state: () => ({
    faves: [],
    favesState: STATES.INIT
  }),
  actions: {
    loadMyData() {
      this.store.favesState = STATES.WIP;
      axios.get('/data')
        .then((res) => {
          this.store.property = res.data;
          this.store.favesState = STATES.DONE;
        })
        .catch((e) => {
          this.store.favesState = STATES.ERROR;
        })
    },
  },
  getters: {
    isLoaded(){
      return this.store.favesState === STATES.DONE;
    }
    isLoading(){
      return this.store.favesState === STATES.WIP;
    }
  }
})

This is, obviously, more verbose, but allows for the components to be smaller and contain less logic. Then, for example, in your component you can use the getter isLoading to display a loading indicator, or use isLoaded inside another component to determine whether to show it.

答案2

得分: 0

是的,这是一种常用的方式来将一些数据加载到Vue应用程序中。

您还可以在beforeMount()created()生命周期钩子之前加载数据(请参阅Vue生命周期图),以防止不必要的HTML更新。

英文:

Yes, this is a oft used way to load some data into the Vue App.

You could also load data before the Mounting in beforeMount() or created() Lifecycle Hooks (see Vue Lifecycle Diagram) to prevent unnecessary HTML updates.

huangapple
  • 本文由 发表于 2023年1月9日 18:33:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/75055985.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定