前端实现数据的分批加载(相当于分页),前端模糊查询

一、分批加载

当前端在渲染dom元素时,数据多的时候渲染非常慢。并且很容易造成页面卡死,解决这个问题通常是用分页来解决的。

分页有两种方式:1、后台进行分页,前端通过传参的方式每次请求接口进行分页。2、前台进行分页,请求一次接口返回所有的数据,前端通过js进行分页。

本文所实现的是:请求一次接口返回所有数据,通过js将所有的数据进行二次分组,分割成每10个(或多个)一组,加载时,先加载一部分,当滚动条滚动时再加载另一部分。这样做:可以在返回数据之后即刻加载出内容,大大提高了用户的浏览性能

下图是对数据重新分组的核心代码:

二、模糊查询

一些业务要求实现搜索查询的功能。这种功能实现也是两种方式:1、后台进行模糊查询,前端调用接口传递相应的参数即可。2、前端进行模糊查询,通过对所有的数据中相应的字段进行正则匹配,将匹配成功的数据放在一个新的数组中,进行渲染。

下图是判断数据和输入内容是否匹配的代码:

三、下面是结合分批加载和模糊查询所做的一个demo

demo地址:https://download.csdn.net/download/hhy1006894859/10856202

1、先引入jquery

2、本文所用到的数据为本地的json文件,需要自己模拟数据

代码:

js:

var totalArr = [];// 总数组,用来存放分割完毕的数组
var count = 10;// 每10个为一组
var totalArrIndex = null;// 用来展示加载总数组哪一项
var allArr = [];//allArr 均为请求接口获得的全部数据
var matchArr = [];// 匹配成功的所有数据存在的数组
var list = null;// 存放调用插件时所传来的list值
var repeatCount = 1;// 由于数据较少,测试的时候需要重复一下数据,这是重复的倍数,即最终数据为请求获得的数据乘以该倍数

// 获得全部的数据的方法
function getAllData(callback) {
    $.ajax({
        url:"../json/fpload.json",
        type:"get",
        dataType:"json",
        success:function (res) {
            console.log("成功",res);
            // 模拟一些假数据,使总数据变得多一些
            allArr = [];// 用来存放全部数据
            for(var i=0;i<1*repeatCount;i++) {
                allArr = allArr.concat(res.resultArray)
            }
            callback(allArr)// 全部数据返回
        },
        error:function (error) {
            // console.log("失败",error)
        }
    })
}

// 将所有数据按照count进行分组
function sliceArr(allArr) {
    totalArr = [];
    for(var i=0;i<allArr.length;i+=count) {
        totalArr.push(allArr.slice(i,i+count))
    }
    console.log("分割完后的数组",totalArr)
    if(totalArr.length == 0) {
        // 没有数据
        nodatafun()
    }
    // 分割完数组之后进行首次加载数据,为了避免只加载第一条没有滚动条出现的问题,使用以下代码使得首次加载完后必定出现滚动条(或者加载完数据)。
    for(var i=0;i<totalArr.length;i++) {
        if($(document).height() <= $(window).height()) {
            // 没有滚动条
            loadData(totalArr[i])
            totalArrIndex = i;
        }else {
            break;
        }
    }
}

// 在页面上渲染数据的方法
function loadData(arr) {
    if(arr.length == 0) {
        // 没有数据
    }else {
        for(var i=0;i<arr.length;i++) {
            // 外层循环渲染card, (即渲染的是有多少个卡片)
            var card = $('<div class="center card"></div>')
            for(var j=0;j<list.length;j++) {
                // 内层渲染li,渲染的是每个卡片的每列内容
                card.append('' +
                    '<div class="center li">' +
                    '<span class="key">'+ list[j].msg +'</span>' +
                    '<span class="value">'+ arr[i][list[j].code] +'</span>' +
                    '</div>'
                )
            }
            $('.cardWrap').append(card)
        }
    }
}

// 判断输入内容和某一项数据是否匹配的方法
function checkfun(value,str,callback) {
    var reg = new RegExp(value);
    var rdata = null;
    if(str.match(reg) != null) {
        // 匹配成功
        rdata = 1;
    }else {
        // 没有匹配到
        rdata = -1
    }
    callback(rdata)
}

// 点击搜索时所调用的方法
function searchfun(callback) {
    matchArr = [];// 先置空存放匹配数据的数组
    var value = $('.search input').val();
    for(var i=0;i<allArr.length;i++) {
        for(var j=0;j<list.length;j++) {
            var isbreak = null;// 判断是否跳出本层循环
            checkfun(value,allArr[i][list[j].code],function (flag) {
                if(flag>0) {
                    // 匹配成功
                    matchArr.push(allArr[i]);
                    isbreak = true;
                }else {
                    // 没有匹配到
                    isbreak = false;
                }
            })
            if(isbreak) {
                break;
            }
        }
    }
    callback()
}

// 清空页面数据的方法
function cleardata() {
    $('.cardWrap').empty();
}

// 加载没有数据的方法
function nodatafun() {
    $(".cardWrap").append('' +
        '<span class="nodata">当前没有数据呦!</span>'
    )
}

// 显示loading
function showload() {
    $('.loadingWrap').show();
}

// 隐藏loading
function hideload() {
    setTimeout(function () {
        $('.loadingWrap').hide();
    },500)
}

let cardPlugin = function(obj) {
    showload();// 初始的时候先显示loading
    list = obj.list;
    $(function () {
        // 获得全部的数据
        getAllData(function (allArr) {
            console.log("接口获得的所有数据",allArr)
            cleardata();// 清空数据
            hideload();// 隐藏loading
            sliceArr(allArr)// 分割数组并进行第一次的加载
        })
    })
    $(function () {
        // 滚动条滚动进行加载数据
        $(document).scroll(function () {
            console.log(totalArrIndex)
            var bottom = $(document).height() - $(document).scrollTop() - $(window).height();
            if(bottom<600) {
                // 设定一个界限,开始加载新的数据
                totalArrIndex++;
                if(totalArrIndex >= totalArr.length) {
                    // 滚动太快,下标超过了数组的长度
                    totalArrIndex = totalArr.length
                    return;
                }
                loadData(totalArr[totalArrIndex])
            }
        })
    })
    $(function () {
        // 点击搜索进行模糊查询
        $("body").on("click",".search button",function () {
            showload();//显示loading
            searchfun(function () {
                console.log("匹配成功的数组",matchArr)
                cleardata();// 清空数据
                hideload();// 隐藏loading
                sliceArr(matchArr)
            })
        })
    })
}

css:(sass)

$card_w:6rem;// card的宽度
$card_bg:#ffffff;// card的背景颜色
$card_rd:0.08rem;// card的圆角
$card_liw:5.6rem;// 每一项的宽度
$card_liminh:0.8rem;// 每一项的最小高度
$card_fz:0.24rem;// card的文字大小
$card_liborcolor:#cccccc;// 每一项的下边框的颜色
$card_keycolor:#4d4d4d;// key的颜色
$card_valuecolor:#808080;// value的颜色
$card_keyminw:2.5rem;// key的最小宽度
$card_mb:0.2rem;// card的marginbottom
$card_nodata_fz:0.24rem;// 没有数据时的文字大小
$card_nodata_color:#4d4d4d;// 没有数据时的文字颜色
$card_search_h:0.5rem;

$load_mt:2rem;// 整个loading的margintop
$load_span:0.2rem;// loading小球的宽高
$load_spanmr:0.3rem;// loading小球间的间距
$load_spanbg:#ffffff;//loading小球的颜色

$box_width:6.4rem;// container的最大宽度和nav的宽度
$body_bg:#f0f0f0;// 四个子页面中body的背景颜色

@mixin border_bottom($color) {
  & {
    position: relative;
    &:before {
      content: "";
      position: absolute;
      top: 0;
      left: 0;
      border-bottom: 1px solid $color;
      transform-origin: 0 0;
      padding: 1px;
      box-sizing: border-box;
      pointer-events: none;
    }
    &:last-child:before {
      border-bottom:none;
    }
  }
  @media (-webkit-min-device-pixel-ratio:1),(min-device-pixel-ratio:1) {
    &:before {
      width: 100%;
      height: 100%;
      transform: scale(1);
    }
  }
  @media (-webkit-min-device-pixel-ratio:2),(min-device-pixel-ratio:2) {
    &:before {
      width: 200%;
      height: 200%;
      transform: scale(0.5);
    }
  }
  @media (-webkit-min-device-pixel-ratio:3),(min-device-pixel-ratio:3) {
    &:before {
      width: 300%;
      height: 300%;
      transform: scale(0.333);
    }
  }
}
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
html {
  font-size: 100px;
}
body {
  padding-top: $card_search_h;
  background: #f0f0f0;
  .search {
    //border: 1px red solid;
    position: fixed;
    top: 0;
    left: 50%;
    width: $card_w;
    margin-left: -$card_w/2;
    height: $card_search_h;
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    padding-right: 0.2rem;
    background: #f0f0f0;
    z-index: 100;
  }
  .cardWrap {
    //border: 1px red solid;
    span.nodata {
      display: block;
      //border: 1px red solid;
      font-size: $card_nodata_fz;
      text-align: center;
      color: $card_nodata_color;
    }
  }
  .center {
    display: block;
    margin: 0 auto;
  }
  .card {
    //border: 1px red solid;
    width: $card_w;
    background: $card_bg;
    border-radius: $card_rd;
    margin-bottom: $card_mb;
    //height: 100px;
    .li {
      width: $card_liw;
      min-height: $card_liminh;
      //border-bottom: 1px #cccccc solid;
      display: flex;
      flex-direction: row;
      justify-content: flex-start;
      align-items: center;
      font-size: $card_fz;
      @include border_bottom($card_liborcolor);
      span.key {
        color: $card_keycolor;
        width: $card_keyminw;
        //border: 1px red solid;
        padding-left: 0.1rem;
      }
      span.value {
        color: $card_valuecolor;
        //flex: 1;
        width: $card_liw - $card_keyminw;
        //border: 1px red solid;
        padding-left: 0.1rem;
        padding-right: 0.1rem;
      }
    }
  }
  // loading动画效果
  .loadingWrap {
    //border: 1px red solid;
    position: fixed;
    top: 0;
    left: 50%;
    margin-left: -$box_width/2;
    width: $box_width;
    height: 100%;
    background: $body_bg;
    z-index: 80;
    display: block;
    .loading{
      //width: 150px;
      //height: 15px;
      margin: 0 auto;
      margin-top:$load_mt;
      //border: 1px red solid;
      display: flex;
      justify-content: center;
      align-items: center;
      span {
        //border: 1px red solid;
        display: inline-block;
        width: $load_span;
        height: $load_span;
        margin-right: $load_spanmr;
        border-radius: 50%;
        background: $load_spanbg;
        -webkit-animation: load 1.04s ease infinite;
        &:last-child {
          margin-right: 0px;
        }
        &:nth-child(1) {
          -webkit-animation-delay:0.13s;
        }
        &:nth-child(2) {
          -webkit-animation-delay:0.26s;
        }
        &:nth-child(3) {
          -webkit-animation-delay:0.39s;
        }
        &:nth-child(4) {
          -webkit-animation-delay:0.52s;
        }
        &:nth-child(5) {
          -webkit-animation-delay:0.65s;
        }
      }
    }
  }
  @-webkit-keyframes load{
    0%{
      opacity: 1;
      -webkit-transform: scale(1.3);
    }
    100%{
      opacity: 0.2;
      -webkit-transform: scale(.3);
    }
  }
}

html:

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <link rel="stylesheet" href="../css/fpload.css">
    <title>分批加载</title>
</head>
<body>
<div class="search">
    <input type="text">
    <button>搜索</button>
</div>
<div class="cardWrap">
    <!--<div class="center card">-->
        <!--<div class="center li">-->
            <!--<span class="key">险种个人编号</span>-->
            <!--<span class="value">0123456789</span>-->
        <!--</div>-->
        <!--<div class="center li">-->
            <!--<span class="key">险种个人编号</span>-->
            <!--<span class="value">0123456789</span>-->
        <!--</div>-->
        <!--<div class="center li">-->
            <!--<span class="key">险种个人编号</span>-->
            <!--<span class="value">0123456789</span>-->
        <!--</div>-->
    <!--</div>-->
</div>
<div class="loadingWrap">
    <div class="loading">
        <span></span>
        <span></span>
        <span></span>
        <span></span>
        <span></span>
    </div>
</div>
</body>
</html>
<script type="text/javascript" src="../js/jquery.min.js"></script>
<script type="text/javascript" src="../js/fpload.js"></script>
<script>
    cardPlugin({
        "list":[
            {"msg":"序号","code":"RN"},
            {"msg":"编号1","code":"AAB001"},
            {"msg":"编号2","code":"AAC001"},
            {"msg":"日期1","code":"AAE003"},
            {"msg":"日期2","code":"AAE002"},
            {"msg":"类别","code":"AAE140"},
            {"msg":"金额","code":"AAC040"},
            {"msg":"支付基数","code":"AAE018"},
            {"msg":"支付总金额","code":"AAE020"},
            {"msg":"个人金额","code":"AAE021"},
            {"msg":"其他金额","code":"AAE022"}
        ]
    })
</script>

所用到的json文件格式如下:

{
"count":105,
"resultArray":[
{
"AAB001":"400000000000",
"AAC001":"200000000000",
"AAE003":"197802",
"AAE140":"保险",
"AAE002":"199602",
"AAC040":"3529.5",
"AAE018":"3529.5",
"AAE020":"0",
"AAE021":"0",
"AAE022":"0",
"RN":"1"
}]}

 

  • 1
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的数据分批加载的代码示例,假设后端 API 返回了一个包含所有数据的数组,前端需要将这些数据分批加载到 el-select 组件中: ``` <template> <el-select v-model="selected" placeholder="请选择" filterable remote :remote-method="loadData"></el-select> </template> <script> export default { data() { return { selected: '', data: [], // 所有数据 pageSize: 50, // 每页数据大小 currentPage: 1, // 当前页码 } }, methods: { // 加载数据 loadData(query) { // 如果已经加载完所有数据,则直接返回 if (this.data.length <= (this.currentPage - 1) * this.pageSize) { return; } // 获取当前页的数据 const start = (this.currentPage - 1) * this.pageSize; const end = Math.min(start + this.pageSize, this.data.length); const currentData = this.data.slice(start, end); // 返回数据和是否有更多数据的标志 this.currentPage++; const hasMore = this.data.length > end; return new Promise(resolve => { resolve({ items: currentData, hasMore: hasMore }); }); }, // 初始化数据 initData() { // 发送请求获取所有数据 fetch('/api/data') .then(response => response.json()) .then(data => { this.data = data; }); }, }, mounted() { this.initData(); }, } </script> ``` 上述示例中,el-select 组件的 `remote` 属性设置为 `true`,表示数据由远程服务器提供。当用户输入关键字时,会调用 `loadData` 方法加载数据。该方法会根据当前页码和每页数据大小,从所有数据中取出当前页的数据,并返回给 el-select 组件。当所有数据都被加载完时,`loadData` 方法会返回一个空 Promise,表示没有更多数据了。在 `initData` 方法中,通过发送请求获取所有数据,保存在 `data` 数组中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值