vue.js+mock.js+node.js实现移动端翻页效果

偶然发现了个好东西:mock.js,它可以用来随机的生成你想要的数据格式,包括文本、图片等,这时候我们再结合node.js,就可以真正的脱离后端,自己做接口,返回数据,测试我们的前端功能模块了。

mock.js的大致使用是通过定义一个自己想要的数据模板,然后数据模板中的数据值可以通过Mock.Random中的一系列方法来生成,最后通过Mock.mock(); 来生成自己想要的数据。

eg:

var tempList={
       'list|10':[{    //list为数据名,|10为生成10条数据
           'id|+1': startId(pagenow),     //+1表示字段id的值自动增长
           'title': '@ctitle(6, 12)',    //通过调用Mock.Random中的ctitle方法随机生成6-12个字的中文,然后作为字段title的值
           'img': mockRandom.image('200x100', '#ccc', '@title'),    //调用image方法,生成宽200高100的图片
           'content': '@cparagraph(1,2)'    //调用cparagraph生成一段中文文本
       }]
   }
具体的用法大家可以移步这里Mock.js用法,大家可以先看下语法规范,然后在看下Mock.Random中的一系列方法,就大致会用了。

mock.js会使用后,接下来就是利用node搭建一个服务器,然后通过接口处理相关分页请求,并把数据返回给前端。这里我用了node的express来搭建,node或者express的用法大家可以去看下菜鸟教程,具体代码如下:

//express_demo.js 文件
var express = require('express');
var app = express();
var Mock = require('mockjs');
var fs = require('fs');
var mockRandom = Mock.Random;
 
var pageCount = 6;    //总的页数
var pagelist = 10;    //每页资讯条数
app.get('/getData',function(req,res){    
    var pagenow = req.query.pagenow;
    console.log(pagenow);
    var    hasMore = true,data=[];
    var tempList={
       'list|10':[{
           'id|+1': startId(pagenow),
           'title': '@ctitle(6, 12)',
           'img': mockRandom.image('200x100', '#ccc', '@title'),
           'content': '@cparagraph(1,2)'
       }]
   }, tempList2={
           'list|1-10':[{
                   'id|+1': startId(pagenow),
                   'title': '@ctitle(6, 12)',
                   'img': mockRandom.image('200x100', '#ccc', '@title'),
                   'content': '@cparagraph(1,2)'
               }]
   };     
   
     if(pagenow==pageCount){
         data = Mock.mock(tempList2); 
         hasMore = false;    //表示已经没有数据
     }else{
         data = Mock.mock(tempList);
         hasMore = true;    //还有数据
     } 
     
   res.json({
       status: true,
       data: data,
       hasMores:hasMore,
       msg: ''
   });
    
});
 
 
function startId(pagenow){
    return (pagenow-1)*pagelist;
}
 
var server = app.listen(8081, function () {
 
  var host = server.address().address
  var port = server.address().port
 
  console.log("应用实例,访问地址为 http://%s:%s", host, port)
 
})
 

这里我固定每页的数据是10条,总共有6页,然后判断前端传过来的当前页面(pagenow)是否是等于总的页面数,如果是就使用第二个数据模板(随机生成1-10条数据),然后hasMore置为false,提示前端没有数据了;否则就使用第一个数据模板(固定生成10条随机的数据),hasMore置为true,提示前端还有数据。

 

接口完成以后,接下来就是搭建前端了。涉及到这些知识点:搭建vue-cli脚手架,设置反向代理,然后通过axios请求接口,获取数据。

具体代码如下:

<template>
    <div class="wrap">
        <div class="item clearfix" v-for="item in newsData">
            <div class="img-box"><img class="img" :src="item.img"/></div>
            <div class="content-box">
                <h4 class="title">Id:{{item.id}} --- Title:  {{item.title}}</h4>
                <div class="content">Content: {{item.content}}</div>
            </div>
        </div>
        <div class="no-more" v-if="!hasMore">已经没有更多数据了!!!</div>
    </div>
</template>
 
<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      msg: 'Welcome to Your Vue.js App',
      newsData:[],
      hasMore: true,        //判断是否还有数据
      pagenow: 1,
      isLoad: true,     //开关,防止滚动到底部时多次加载
    }
  },
  mounted: function(){
      this.loadData();
        //console.log(this.newsData,'newsData')
        window.addEventListener('scroll',this.scrollEvent);        //添加滚动事件监听
        
  },
  methods:{
      loadData:function(cb){
            let that = this;
            if(that.hasMore){    
                that.$http.get('/getData?pagenow='+that.pagenow).then(function(res){
                  console.log(res);
                  if(res.data.status){
                      //that.newsData = that.newsData.concat(res.data.data.list);
                      let len = res.data.data.list.length;
                      for(let i = 0;i<len;i++){
                          that.newsData.push(res.data.data.list[i]);
                      }
                      that.hasMore = res.data.hasMores;
                      that.pagenow ++;
                      cb && cb();    
                  }
              })
              .catch(function(res){
                  console.log(res);
              });    
            }
 
      },
      
      scrollEvent:function(e){    //监听滚动事件
          var that = this;
          if(this.getScrollHeight()-this.getScrollTop()-this.getWindowHeight()==0){
              //alert('到底了!!!')
              if(this.isLoad){
                  this.isLoad = false;
                  this.loadData(function(){
                      that.isLoad = true;        //等获取到数据以后在开启开关
                  });
              }
              
          }
          
      },
      //滚动条在Y轴上的滚动距离
      getScrollTop:function(){
          var scrollTop = 0, bodyScrollTop = 0, documentScrollTop = 0;
          if(document.body){
            bodyScrollTop = document.body.scrollTop;
          }
          if(document.documentElement){
            documentScrollTop = document.documentElement.scrollTop;
          }
          scrollTop = (bodyScrollTop - documentScrollTop > 0) ? bodyScrollTop : documentScrollTop;
          return scrollTop;
        },
         
        //文档的总高度
        getScrollHeight: function(){
          var scrollHeight = 0, bodyScrollHeight = 0, documentScrollHeight = 0;
          if(document.body){
            bodyScrollHeight = document.body.scrollHeight;
          }
          if(document.documentElement){
            documentScrollHeight = document.documentElement.scrollHeight;
          }
          scrollHeight = (bodyScrollHeight - documentScrollHeight > 0) ? bodyScrollHeight : documentScrollHeight;
          return scrollHeight;
        },
         
        //浏览器视口的高度
        getWindowHeight: function(){
          var windowHeight = 0;
          if(document.compatMode == "CSS1Compat"){
            windowHeight = document.documentElement.clientHeight;
          }else{
            windowHeight = document.body.clientHeight;
          }
          return windowHeight;
        },
      
  }
}
</script>
 
<style>
    .wrap{width: 95%; margin: .3rem auto 0; line-height: .42rem;}
    .item{width: 100%; padding: .2rem 0; border: 1px solid #42B983; box-sizing: border-box; margin: .1rem 0;}
    .img-box{width: 1.4rem; height: 1.4rem; margin-top: .3rem; margin-left: .1rem; border: 1px solid #333; float: left;}
    .img-box .img{width: 100%; height: 100%;}
    .content-box{width: 72%; float: right;}
    .title{font-size: .36rem; text-align: left;}
    .content{font-size: .28rem; text-align: left; margin-top: .1rem;}
    .no-more{padding: .2rem; text-align: center; font-size: .32rem; color: red;}
</style>
前端这边首先在mounted生命周期发起了一次请求获取了第一页的数据, 然后添加了个滚动监听,判断是否滚动到底部,到底了后执行加载数据的方法,然后判断后端返回的hasMore是否为true,是滚动到底了继续发起请求,获取下一个页面的数据。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值