我在使用 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>
todosModule.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
}
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号
好吧,我自己找到了解决方案。
最重要的是观察者。我向 TodoListPaginationView.vue 添加了下一个代码: