瀑布流布局已然完成,那么剩下的就是另一个比较大的工程了——无限加载。

之前说了,这个活动项目是基于SUI-Mobile搭建的,所以可以直接使用sui内建组件“无限加载”来实现这个功能。

没有真实的数据,所有数据都是自己创建的假数据

以works.json为例:

[
  {
    "id": 1,
    "src": "http://cued.xunlei.com/demos/publ/img/P_000.jpg",
    "numbering":"00001",
    "school":"双语小学",
    "student":"王伟",
    "praise":"23",
    "isDel": true,
    "delDesc": "图片不符合法律要求",
    "name": "美美的一天",
    "todayClk": false,
    "isPraise": false
  },
  ...     
]

一个数组,里面是一个个的对象。

最开始实现的时候,是在methods对象里面定义一个初始化请求函数,一个分页请求函数

      fetchData(fn){
        var _this = this;
        axios.get("./src/assets/data/worksRank.json").then(function (res) {
          _this.worksList=res.data
          if (typeof fn =="function") fn();
        })
      },
      loadingMore(){
        var _this = this;
        var loading = false;

        // 每次加载添加多少条目
        var itemsPerLoad = 10,
            page = 2;
        // 注册'infinite'事件处理函数
        $(document).on('infinite',  function() {
          
          // 如果正在加载,则退出
          if (loading) return;

          // 设置flag
          loading = true;

          // 模拟1s的加载过程,实际项需要调用ajax向后台取数据
       
              // 重置加载flag
          axios.get('./src/assets/data/worksRank.json', {
              page: page,
              val: ""
            }).then(function (response) {
              loading = false;

              
              //添加判断条件  如果返回的数组的数据小于每页应当加载的数据条数,则表示加载完毕
              if (response.data.length < itemsPerLoad) {
                  // 加载完毕,则注销无限加载事件,以防不必要的加载
                  $.detachInfiniteScroll($('.infinite-scroll'));
                  // 删除加载提示符
                  $('.infinite-scroll-preloader').remove();
                  return;
              }

              // 添加新条目
              // _this.addWorks(response.data);
              _this.worksList = _this.worksList.concat(response.data);
              page++;
              //容器发生改变,如果是js滚动,需要刷新滚动
              $.refreshScroller();
            });
        });
      }

然后在mounted内调用这两个函数,发现很快实现该无限加载的功能了。再继续研究下去,也受到一片文章的启发,其实所谓无限加载,不就是我们常说的分页么?

改变思路如下:

当页面滑动到底部的时候,仅仅增加页码,然后监听页码的变化,然后调用初始化时候的ajax请求,去请求后台数据。

      loadingMore(){
        var _this = this;
        // 注册'infinite'事件处理函数
        $(document).on('infinite', function() {
          // 如果正在加载,则退出
          if (_this.loading) return;
          // 设置flag
          _this.loading = true;
          // 无限加载,其实就是类似于分页的效果,增加页码
          _this.page++;
        });
      },
    watch: {
      page: function () {
        this.ajaxData();
      }
    }

向后台请求数据,需要带两个参数,一个是页码page,一个是值val,该值是为了搜索功能使用。

其他的操作全部放在ajax请求内部操作:

      ajaxData(){
        axios.get('./src/assets/data/works.json',{
          page: this.page,
          val: this.val
        }).then(function (response) {
          this.loading = false;
          // 为了美观,这里对获取到的推按进行了随机数的处理,实际项目中,不需要额外处理
          response.data.forEach(function (item, index) {
            var num = Math.ceil(Math.random()*162);
            num = num < 10 ? "00"+num : num < 100 ? "0" + num : num;
            item.src = item.src.replace(/[\d]+/, num);
            // 预加载
            var img = new Image();
            img.src = item.src;
          });

          //添加判断条件  如果返回的数组的数据小于每页应当加载的数据条数,则表示加载完毕
          if (response.data.length < this.items) {
              // 加载完毕,则注销无限加载事件,以防不必要的加载
              $.detachInfiniteScroll($('.infinite-scroll'));
              // 删除加载提示符
              $('.infinite-scroll-preloader').remove();
              return;
          }
          if (this.page == 1) {
            this.works = response.data;
          } else {
            this.works = this.works.concat(response.data);
          }

          // 如果是下拉刷新的话
          $.pullToRefreshDone('.pull-to-refresh-content');

        }.bind(this));
      },

对于返回数据循环操作这一步可以不予关注,我这里主要是为了获取不同的图片,进行的随机数,实际请求过程中,每次返回的都是不同数据,不存在这一过程。

还有一个判断 :

          if (this.page == 1) {
            this.works = response.data;
          } else {
            this.works = this.works.concat(response.data);
          }

 这里需要判断当前页码是否为1,如果为1的话,返回的数据直接赋值给works,如果不是1,则在原有值的基础上追加,目的是方便下拉刷新和搜索。

 原以为到这里,已经彻底完成工作,但是在多次测试之后发现,还有一个更大的bug在那呢!

 路由跳转之后,必须刷新页面,才能实现新页面的无限加载,发现该问题之后,立即意识到了问题之所在:

   由于路由点击之后,并没有为document绑定infinite事件,导致跳转之后的页面无法触发infinite事件,就无法实现无限加载。

解决问题的思路在于:在路由跳转页面的时候,关闭之前组件绑定的infinite事件,而在新组件中重新绑定infinite事件。

查询vue-router官方文档,发现“导航钩子”这一说法,共有三个钩子函数:

  • beforeRouteEnter
  • beforeRouteUpdate (2.2 新增)
  • beforeRouteLeave

这里需要用到的是beforeRouteLeave,在路由跳转离开的时候,关闭当前页面注册的“无限滚动事件”,在新组件mounted的时候重新绑定无限滚动事件”,代码修改为:

   beforeRouteLeave (to, from, next) {
      this.page =1;
      $.detachInfiniteScroll($(".infinite-scroll"));
      next(true);
    },

  

    mounted(){
      $.init()
      this.refresh();
      this.ajaxData();
      this.loadingMore();
      $.attachInfiniteScroll($(".infinite-scroll"));
    },

至此,使用vuejs搭配SUI-Mobile的瀑布流布局真正实现了,其中也遇到了各种槽点,初学vuejs,总得付出点填坑的代价的。  

 

posted on 2017-04-21 11:11  烛火星光  阅读(6717)  评论(0编辑  收藏  举报