搜尋

首頁  >  問答  >  主體

如何在 Vue.js 2 中進行正確的分頁

我在使用 vue 建立分頁時遇到問題。我的任務是確保當您單擊按鈕的數字時,會載入 jsonplaceholder 中的新任務。

我已成功載入第一頁和第二頁。我認為這與我的 this.fetchTodos() 操作直接相關。我剛剛學習 vue,需要幫助弄清楚如何在不加載的情況下移動到新頁面時更新資料。

在這種情況下,需要改變頁面的url(取得請求)。我的頁面狀態正在更改,但單擊第三頁時未加載帖子。

下面是四個文件的程式碼,我認為可以幫助您了解情況。

也許使用 GitHub 會更容易,請檢查分頁分支

預先感謝您的幫忙!如果您有疑問或需要更多信息,請寫在評論中

TodoListView.vue - 是起始頁面,其中todos 取得並呈現在頁面上。

<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 - 是第二個文件,在點擊分頁時載入第二個頁面和另一個頁面。

<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 - 第三個文件,其中是分頁邏輯。 Ui引導程式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>

toddModule.js - 最後一個文件,其中是 todos 的 vuex 邏輯。

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 天前431

全部回覆(1)我來回復

  • P粉702946921

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

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

    最重要的是觀察者。我為 TodoListPaginationView.vue 新增了下一個程式碼:

    sssccc
    
    
    
    sssccc

    回覆
    0
  • 取消回覆