英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论