最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • SpringBoot+Vue豆宝社区前后端分离项目手把手实战系列教程14---帖子列表分页功能实现

    正文概述 掘金(豆约翰)   2021-03-07   457

    豆宝社区项目实战教程简介

    本项目实战教程配有免费视频教程,配套代码完全开源。手把手从零开始搭建一个目前应用最广泛的Springboot+Vue前后端分离多用户社区项目。本项目难度适中,为便于大家学习,每一集视频教程对应在Github上的每一次提交。

    项目首页截图

    SpringBoot+Vue豆宝社区前后端分离项目手把手实战系列教程14---帖子列表分页功能实现

    代码开源地址

    前端 后端

    视频教程地址

    视频教程

    前端技术栈

    Vue Vuex Vue Router Axios Bulma Buefy Element Vditor DarkReader

    后端技术栈

    Spring Boot Mysql Mybatis MyBatis-Plus Spring Security JWT Lombok

    分页前端

    1.src\components创建Pagination\index.vue

    <template>
      <div :class="{ hidden: hidden }" class="pagination-container">
        <el-pagination
          :background="background"
          :current-page.sync="currentPage"
          :page-size.sync="pageSize"
          :layout="layout"
          :page-sizes="pageSizes"
          :total="total"
          v-bind="$attrs"
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
        />
      </div>
    </template>
    
    <script>
    import {scrollTo} from "@/utils/scroll-to";
    export default {
      name: "Pagination",
      props: {
        total: {
          required: true,
          type: Number,
        },
        page: {
          type: Number,
          default: 1,
        },
        limit: {
          type: Number,
          default: 10,
        },
        pageSizes: {
          type: Array,
          default() {
            return [5, 10, 20, 30, 50];
          },
        },
        layout: {
          type: String,
          default: "total, sizes, prev, pager, next, jumper",
          // default: 'sizes, prev, pager, next, jumper'
        },
        background: {
          type: Boolean,
          default: true,
        },
        autoScroll: {
          type: Boolean,
          default: true,
        },
        hidden: {
          type: Boolean,
          default: false,
        },
      },
      computed: {
        currentPage: {
          get() {
            return this.page;
          },
          set(val) {
            this.$emit("update:page", val);
          },
        },
        pageSize: {
          get() {
            return this.limit;
          },
          set(val) {
            this.$emit("update:limit", val);
          },
        },
      },
      methods: {
        handleSizeChange(val) {
          this.$emit("pagination", { page: this.currentPage, limit: val });
          if (this.autoScroll) {
            scrollTo(0, 800);
          }
        },
        handleCurrentChange(val) {
          this.$emit("pagination", { page: val, limit: this.pageSize });
          if (this.autoScroll) {
            scrollTo(0, 800);
          }
        },
      },
    };
    </script>
    
    <style scoped>
    .pagination-container {
      /* background: #fff; */
      padding: 5px 0px;
    }
    .pagination-container.hidden {
      display: none;
    }
    </style>
    

    2.src\utils创建scroll-to.js

    Math.easeInOutQuad = function(t, b, c, d) {
        t /= d / 2
        if (t < 1) {
          return c / 2 * t * t + b
        }
        t--
        return -c / 2 * (t * (t - 2) - 1) + b
      }
      
      // requestAnimationFrame for Smart Animating http://goo.gl/sx5sts
      var requestAnimFrame = (function() {
        return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function(callback) { window.setTimeout(callback, 1000 / 60) }
      })()
      
      /**
       * Because it's so fucking difficult to detect the scrolling element, just move them all
       * @param {number} amount
       */
      function move(amount) {
        document.documentElement.scrollTop = amount
        document.body.parentNode.scrollTop = amount
        document.body.scrollTop = amount
      }
      
      function position() {
        return document.documentElement.scrollTop || document.body.parentNode.scrollTop || document.body.scrollTop
      }
      
      /**
       * @param {number} to
       * @param {number} duration
       * @param {Function} callback
       */
      export function scrollTo(to, duration, callback) {
        const start = position()
        const change = to - start
        const increment = 20
        let currentTime = 0
        duration = (typeof (duration) === 'undefined') ? 500 : duration
        var animateScroll = function() {
          // increment the time
          currentTime += increment
          // find the value with the quadratic in-out easing function
          var val = Math.easeInOutQuad(currentTime, start, change, duration)
          // move the document.body
          move(val)
          // do the animation unless its over
          if (currentTime < duration) {
            requestAnimFrame(animateScroll)
          } else {
            if (callback && typeof (callback) === 'function') {
              // the animation is done so lets callback
              callback()
            }
          }
        }
        animateScroll()
      }
    

    3.修改src\views\post\index.vue

    以下是index.vue的全部内容

    SpringBoot+Vue豆宝社区前后端分离项目手把手实战系列教程14---帖子列表分页功能实现

    <template>
      <div>
        <el-card shadow="never">
          <div slot="header" class="clearfix">
            <el-tabs v-model="activeName" @tab-click="handleClick">
              <el-tab-pane label="最新主题" name="latest">
                <article v-for="(item, index) in articleList" :key="index" class="media">
                  <div class="media-left">
                    <figure class="image is-48x48">
                      <img :src="`https://cn.gravatar.com/avatar/${item.userId}?s=164&d=monsterid`" style="border-radius: 5px;">
                    </figure>
                  </div>
                  <div class="media-content">
                    <div class="">
                      <p class="ellipsis is-ellipsis-1">
                        <el-tooltip class="item" effect="dark" :content="item.title" placement="top">
                          <router-link :to="{name:'post-detail',params:{id:item.id}}">
                            <span class="is-size-6">{{ item.title }}</span>
                          </router-link>
                        </el-tooltip>
                      </p>
                    </div>
                    <nav class="level has-text-grey is-mobile  is-size-7 mt-2">
                      <div class="level-left">
                        <div class="level-left">
                          <router-link class="level-item" :to="{ path: `/member/${item.username}/home` }">
                            {{ item.alias }}
                          </router-link>
    
                          <span class="mr-1">
                            发布于:{{ dayjs(item.createTime).format("YYYY/MM/DD") }}
                          </span>
    
                          <span
                            v-for="(tag, index) in item.tags"
                            :key="index"
                            class="tag is-hidden-mobile is-success is-light mr-1"
                          >
                            <router-link :to="{ name: 'tag', params: { name: tag.name } }">
                              {{ "#" + tag.name }}
                            </router-link>
                          </span>
    
                          <span class="is-hidden-mobile">浏览:{{ item.view }}</span>
                        </div>
                      </div>
                    </nav>
                  </div>
                  <div class="media-right" />
                </article>
              </el-tab-pane>
              <el-tab-pane label="热门主题" name="hot">
                <article v-for="(item, index) in articleList" :key="index" class="media">
                  <div class="media-left">
                    <figure class="image is-48x48">
                      <img :src="`https://cn.gravatar.com/avatar/${item.userId}?s=164&d=monsterid`" style="border-radius: 5px;">
                    </figure>
                  </div>
                  <div class="media-content">
                    <div class="">
                      <p class="ellipsis is-ellipsis-1">
                        <el-tooltip class="item" effect="dark" :content="item.title" placement="top">
                          <router-link :to="{name:'post-detail',params:{id:item.id}}">
                            <span class="is-size-6">{{ item.title }}</span>
                          </router-link>
                        </el-tooltip>
                      </p>
                    </div>
                    <nav class="level has-text-grey is-mobile  is-size-7 mt-2">
                      <div class="level-left">
                        <div class="level-left">
                          <router-link class="level-item" :to="{ path: `/member/${item.username}/home` }">
                            {{ item.alias }}
                          </router-link>
    
                          <span class="mr-1">
                            发布于:{{ dayjs(item.createTime).format("YYYY/MM/DD") }}
                          </span>
    
                          <span
                            v-for="(tag, index) in item.tags"
                            :key="index"
                            class="tag is-hidden-mobile is-success is-light mr-1"
                          >
                            <router-link :to="{ name: 'tag', params: { name: tag.name } }">
                              {{ "#" + tag.name }}
                            </router-link>
                          </span>
    
                          <span class="is-hidden-mobile">浏览:{{ item.view }}</span>
                        </div>
                      </div>
                    </nav>
                  </div>
                  <div class="media-right" />
                </article>
              
              
              </el-tab-pane>
               <el-tab-pane label="最近修改" name="update">
                <article v-for="(item, index) in articleList" :key="index" class="media">
                  <div class="media-left">
                    <figure class="image is-48x48">
                      <img :src="`https://cn.gravatar.com/avatar/${item.userId}?s=164&d=monsterid`" style="border-radius: 5px;">
                    </figure>
                  </div>
                  <div class="media-content">
                    <div class="">
                      <p class="ellipsis is-ellipsis-1">
                        <el-tooltip class="item" effect="dark" :content="item.title" placement="top">
                          <router-link :to="{name:'post-detail',params:{id:item.id}}">
                            <span class="is-size-6">{{ item.title }}</span>
                          </router-link>
                        </el-tooltip>
                      </p>
                    </div>
                    <nav class="level has-text-grey is-mobile  is-size-7 mt-2">
                      <div class="level-left">
                        <div class="level-left">
                          <router-link class="level-item" :to="{ path: `/member/${item.username}/home` }">
                            {{ item.alias }}
                          </router-link>
    
                          <span class="mr-1">
                            发布于:{{ dayjs(item.createTime).format("YYYY/MM/DD") }}
                          </span>
    
                          <span
                            v-for="(tag, index) in item.tags"
                            :key="index"
                            class="tag is-hidden-mobile is-success is-light mr-1"
                          >
                            <router-link :to="{ name: 'tag', params: { name: tag.name } }">
                              {{ "#" + tag.name }}
                            </router-link>
                          </span>
    
                          <span class="is-hidden-mobile">浏览:{{ item.view }}</span>
                        </div>
                      </div>
                    </nav>
                  </div>
                  <div class="media-right" />
                </article>
              
              
              </el-tab-pane>
            </el-tabs>
          </div>
    
          <!--分页-->
          <pagination
            v-show="page.total > 0"
            :total="page.total"
            :page.sync="page.current"
            :limit.sync="page.size"
            @pagination="init"
          />
        </el-card>
      </div>
    </template>
    
    <script>
    import { getList } from '@/api/post'
    import Pagination from '@/components/Pagination'
    export default {
      name: 'TopicList',
      components: { Pagination },
      data() {
        return {
          activeName: 'latest',
          articleList: [],
          page: {
            current: 1,
            size: 10,
            total: 0,
            tab: 'latest'
          }
        }
      },
      created() {
        this.init(this.tab)
      },
      methods: {
        init(tab) {
          getList(this.page.current, this.page.size, tab).then((response) => {
            const { data } = response
            this.page.current = data.current
            this.page.total = data.total
            this.page.size = data.size
            this.articleList = data.records
          })
        },
        handleClick(tab) {
          this.init(tab.name)
        }
      }
    }
    </script>
    
    <style scoped>
    </style>
    

    4.测试问题

    测试页面还没分页,需要后端完成分页后显示

    分页后端

    MybatisPlusConfig

    @Configuration
    public class MybatisPlusConfig {
    
        /**
         * 新的分页插件,一缓和二缓遵循mybatis的规则,
         * 需要设置 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存出现问题(该属性会在旧插件移除后一同移除)
         */
        @Bean
        public MybatisPlusInterceptor mybatisPlusInterceptor() {
            MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
            interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
            return interceptor;
        }
    
        @Bean
        public ConfigurationCustomizer configurationCustomizer() {
            return configuration -> configuration.setUseDeprecatedExecutor(false);
        }
    }
    

    测试页面

    SpringBoot+Vue豆宝社区前后端分离项目手把手实战系列教程14---帖子列表分页功能实现


    起源地下载网 » SpringBoot+Vue豆宝社区前后端分离项目手把手实战系列教程14---帖子列表分页功能实现

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元