J'ai un problème pour créer une pagination avec vue. Ma tâche est de m'assurer que lorsque vous cliquez sur le numéro du bouton, une nouvelle tâche dans le jsonplaceholder est chargée.
J'ai chargé la première et la deuxième page avec succès. Je pense que cela est directement lié à mon opération this.fetchTodos(). J'apprends juste Vue et j'ai besoin d'aide pour comprendre comment mettre à jour les données lors du déplacement vers une nouvelle page sans chargement.
Dans ce cas, l'url de la page doit être modifiée (get request). Le statut de ma page change mais la publication ne se charge pas lorsque je clique sur la troisième page.
Vous trouverez ci-dessous le code de quatre fichiers qui, je pense, vous aideront à comprendre la situation.
Ce serait peut-être plus facile d'utiliser GitHub, consultez la branche paginée
Merci d'avance pour votre aide ! Si vous avez des questions ou avez besoin de plus d'informations, écrivez-nous dans les commentaires
TodoListView.vue - est la page de démarrage où les tâches sont récupérées et affichées sur la page.
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script> <template> <div class="todolist"> <ContainerBootstrap> <div class="row"> <div class="col-12 text-center"> <TitlePage v-if="todos" text="Список задач"/> <TitlePage v-else text="Список задач пуст, создайте новую!"/> <button-bootstrap data-bs-toggle="modal" data-bs-target="#createTodo" css-class="btn-lg btn-primary mt-2 mb-4">Создать задачу</button-bootstrap> <ModalBootstrap @create="createTodo" :todos="todos" css-id="createTodo"/> <SearchBootstrap v-if="todos" @search="searchTodo"/> <div v-if="todos" class="d-flex justify-content-end mt-2"> <button-bootstrap @click.native="setCompletedToAllTodo()" css-class="btn-lg btn-success">Отменить всё как "Выполненные"</button-bootstrap> </div> </div> </div> <TodoList v-if="todos" :todos="searchedTodos"/> <PaginationBootstrap :page="page" :total-pages="totalPages" class="mt-4"/> </ContainerBootstrap> </div> </template> <script> import ContainerBootstrap from "@/components/UI/ContainerBootstrap"; import TitlePage from "@/components/TitlePage"; import TodoList from "@/components/TodoList"; import {mapState, mapActions, mapMutations, mapGetters} from 'vuex' import ButtonBootstrap from "@/components/UI/ButtonBootstrap"; import ModalBootstrap from "@/components/UI/ModalBootstrap"; import SearchBootstrap from "@/components/UI/SearchBootstrap"; import PaginationBootstrap from "@/components/UI/PaginationBootstrap"; export default { name: "TodoListView", components: { PaginationBootstrap, SearchBootstrap, ModalBootstrap, TodoList , ButtonBootstrap, TitlePage, ContainerBootstrap}, data: function() { return { isShow: false, } }, methods: { ...mapActions({ fetchTodos: "todos/fetchTodos" }), ...mapMutations({ setSearchQuery: 'todos/setSearchQuery' }), createTodo(todo) { this.$store.commit('todos/addTodo', todo); }, setCompletedToAllTodo() { console.log('hello') this.$store.commit('todos/setCompletedToAllTodo') }, searchTodo(query) { this.$store.state.todos.searchQuery = query; } }, mounted() { this.fetchTodos() }, computed: { ...mapState({ todos: state => state.todos.todos, isTodosLoading: state => state.todos.isTodosLoading, page: state => state.todos.page, limit: state => state.todos.limit, totalPages: state => state.todos.totalPages, searchQuery: state => state.todos.searchQuery }), ...mapGetters({ searchedTodos: 'todos/searchedTodos' }) } } </script>
TodoListPaginationView - est le deuxième fichier qui charge la deuxième page et une autre page lorsque l'on clique sur la pagination.
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script> <template> <div class="todolist"> <ContainerBootstrap> <div class="row"> <div class="col-12 text-center"> <TitlePage :text="'Страница №'+ page"/> <router-link to="/todolist"> <button-bootstrap css-class="btn-lg btn-primary mt-2 mb-4">Вернуться к началу</button-bootstrap> </router-link> </div> <TodoList v-if="todos" :todos="searchedTodos"/> <PaginationBootstrap :page="page" :total-pages="totalPages" class="mt-4"/> </div> </ContainerBootstrap> </div> </template> <script> import ContainerBootstrap from "@/components/UI/ContainerBootstrap"; import TitlePage from "@/components/TitlePage"; import ButtonBootstrap from "@/components/UI/ButtonBootstrap"; import TodoList from "@/components/TodoList"; import {mapActions, mapGetters, mapMutations, mapState} from "vuex"; import PaginationBootstrap from "@/components/UI/PaginationBootstrap"; export default { name: "TodoListPaginationView", components: {PaginationBootstrap, TodoList, ButtonBootstrap, TitlePage, ContainerBootstrap}, methods: { ...mapActions({ fetchTodos: "todos/fetchTodos", }), ...mapMutations({ setSearchQuery: 'todos/setSearchQuery' }) }, computed: { ...mapState({ todos: state => state.todos.todos, isTodosLoading: state => state.todos.isTodosLoading, page: state => state.todos.page, limit: state => state.todos.limit, totalPages: state => state.todos.totalPages, searchQuery: state => state.todos.searchQuery }), ...mapGetters({ searchedTodos: 'todos/searchedTodos' }) }, mounted() { this.fetchTodos() }, } </script>
PaginationBootstrap.vue - Le troisième fichier, qui est la logique de pagination. Fichier d'amorçage de l'interface utilisateur 5.
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script> <template> <nav aria-label="Page navigation example"> <ul class="pagination"> <li class="page-item"><a class="page-link" href="#">Предыдущая</a></li> <li v-for="pageNumber in totalPages" :key="pageNumber" :class="{'active' : page === pageNumber}" class="page-item"> <span @click="changePage(pageNumber)" class="page-link">{{pageNumber}}</span> </li> <li class="page-item"><a class="page-link" href="#">Далее</a></li> </ul> </nav> </template> <script> export default { name: "PaginationBootstrap", props: { page: Number, totalPages: Number }, methods: { changePage(pageNumber) { this.$store.commit('todos/setPage', pageNumber); if (pageNumber === 1) { this.$router.push('/todolist') } else { this.$router.push({name: 'todolistPagination', params: {page: pageNumber}}) } } } } </script> <style lang="scss" scoped> .pagination { .page-item { .page-link { cursor: pointer; } } } </style>
todosModule.js - Le dernier fichier, qui est la logique vuex de todos.
import axios from "axios"; export const todosModule = { state: () => ({ todos: [], page: 1, limit: 10, totalPages: 0, isTodosLoading: false, searchQuery: '', }), mutations: { setTodos(state, todos) { state.todos = todos }, setPage(state, page) { state.page = page }, setTotalPages(state, totalPages) { state.totalPages = totalPages }, setLoadingTodos(state, bool) { state.isTodosLoading = bool }, setCompleted(state, completed) { const index = state.todos.findIndex(todo => todo.id === completed.id); state.todos[index].completed = completed.completed }, setCompletedToAllTodo(state) { state.todos.map(obj => { obj.completed = true }) }, removeTodo(state, id) { const index = state.todos.findIndex(todo => todo.id === id) state.todos.splice(index, 1) }, addTodo(state, todo) { state.todos.unshift(todo); }, setTitle(state, tusk) { const index = state.todos.findIndex(todo => todo.id === tusk.id); state.todos[index].title = tusk.title }, setSearchQuery(state, searchQuery) { state.searchQuery = searchQuery; } }, actions: { async fetchTodos({state, commit}) { try { commit('setLoadingTodos' , true) const response = await axios.get('https://jsonplaceholder.typicode.com/todos', { params: { _page: state.page, _limit: state.limit } }) commit('setTotalPages', Math.ceil(response.headers['x-total-count'] / state.limit)) commit('setTodos', response.data) } catch (e) { console.log(e) } finally { commit('setLoadingTodos', false) } }, async getCurrentPage({commit}, currentPage) { try { commit('setPage', currentPage) } catch (e) { console.log(e); } } }, getters: { searchedTodos(state) { return [...state.todos].filter(todo => todo.title.toLowerCase().includes(state.searchQuery.toLowerCase())) }, }, namespaced: true }
Eh bien, j'ai trouvé la solution moi-même.
La chose la plus importante est l'observateur. J'ai ajouté le code suivant à TodoListPaginationView.vue :