suchen

Heim  >  Fragen und Antworten  >  Hauptteil

So führen Sie die richtige Paginierung in Vue.js 2 durch

Ich habe ein Problem beim Erstellen einer Paginierung mit Vue. Meine Aufgabe besteht darin, sicherzustellen, dass beim Klicken auf die Nummer der Schaltfläche eine neue Aufgabe im jsonplaceholder geladen wird.

Ich habe die erste und zweite Seite erfolgreich geladen. Ich denke, das hängt direkt mit meiner this.fetchTodos()-Operation zusammen. Ich lerne gerade Vue und brauche Hilfe dabei, herauszufinden, wie ich Daten aktualisieren kann, wenn ich auf eine neue Seite wechsle, ohne sie zu laden.

In diesem Fall muss die URL der Seite geändert werden (Anfrage abrufen). Der Status meiner Seite ändert sich, aber der Beitrag wird nicht geladen, wenn ich auf die dritte Seite klicke.

Nachfolgend finden Sie den Code für vier Dateien, der Ihnen meiner Meinung nach helfen wird, die Situation zu verstehen.

Vielleicht wäre es einfacher, GitHub zu verwenden, schauen Sie sich den paginierten Zweig an

Vielen Dank im Voraus für Ihre Hilfe! Wenn Sie Fragen haben oder weitere Informationen benötigen, schreiben Sie bitte in die Kommentare

TodoListView.vue – ist die Startseite, auf der Aufgaben abgerufen und auf der Seite gerendert werden.

<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 – ist die zweite Datei, die die zweite Seite und eine weitere Seite lädt, wenn auf Paginierung geklickt wird.

<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 – Die dritte Datei, die die Paging-Logik darstellt. Ui Bootstrap 5-Datei.

<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 – Die letzte Datei, die die Vuex-Logik von todos darstellt.

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
}

P粉690200856P粉690200856247 Tage vor430

Antworte allen(1)Ich werde antworten

  • P粉702946921

    P粉7029469212024-03-28 09:08:55

    好吧,我自己找到了解决方案。

    最重要的是观察者。我向 TodoListPaginationView.vue 添加了下一个代码:

    
    
    
    
    

    Antwort
    0
  • StornierenAntwort