0👍
Here’s the store mechanics:
const { createApp, onMounted, computed } = Vue;
const { createStore } = Vuex;
const store = createStore({
state: {
profiles: [],
visibleProfilesCount: 0,
loading: false
},
actions: {
// replace with actual call to server
loadMoreProfiles({ commit, state }) {
commit('setLoading', true);
return new Promise((resolve) => {
setTimeout(() => {
commit(
"addProfiles",
Array.from({ length: 30 }).map(
(_, key) => key + state.profiles.length
)
);
commit('setLoading', false);
resolve();
}, 1e3);
});
},
},
mutations: {
addProfiles(state, profiles) {
state.profiles.push(...profiles);
},
setLoading(state, loading) {
state.loading = loading;
},
showMoreProfiles(state) {
state.visibleProfilesCount += 10;
},
},
getters: {
visibleProfiles(state) {
return state.profiles.slice(0, state.visibleProfilesCount);
},
},
});
const app = createApp({
setup() {
const showMore = () => {
store.commit("showMoreProfiles");
if (store.state.profiles.length < store.state.visibleProfilesCount) {
store.dispatch("loadMoreProfiles");
}
};
onMounted(showMore);
return {
visibleProfiles: computed(() => store.getters.visibleProfiles),
loading: computed(() => store.state.loading),
showMore,
};
},
});
app.use(store);
app.mount("#app");
.logger {
position: fixed;
width: 50vw;
top: 0;
bottom: 0;
right: 0;
}
<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
<script src="https://unpkg.com/vuex@4"></script>
<div id="app">
<div v-for="profile in visibleProfiles" :key="profile">{{ profile }}</div>
<div v-if="loading">Loading...</div>
<button v-else @click="showMore">Load more</button>
<pre class="logger" v-text="JSON.stringify({
profiles: $store.state.profiles.length,
visibleProfiles: $store.state.visibleProfilesCount,
loading
}, null, 2)"></pre>
</div>
All that’s left is to link showMore
to the scroll action, instead of the button, and replace loadMoreProfiles
action with an actual call to server to get the more profiles and add them to state.
Obviously, you don’t have to keep visibleProfilesCount
and visibleProfiles
in the store. They can be declared in your component, along these lines:
const visibleProfilesCount = ref(0)
const visibleProfiles = computed(
() => store.state.profiles.slice(0, visibleProfilesCount.value)
)
const showMore = () => {
visibleProfilesCount.value += 10;
if (store.state.profiles.length < visibleProfilesCount.value) {
store.dispatch("loadMoreProfiles");
}
};
The gist of it is: visibleProfiles
is computed
, or getter
on store, (which means derived state), resulting from two other state properties: profiles
and visibleProfilesCount
. Whenever one of the state props changes, the computed
changes.
- [Vuejs]-Vue2 Vite project with mixed TS and JS giving error TS9006
- [Vuejs]-Vuetify: autocomplete components unable to build as the expected
Source:stackexchange.com