業務需求:json
列表滾動到底部時,繼續往上拉,加載更多內容小程序
必備參數:數組
(1)pageindex: 1 //第幾回加載網絡
(2)callbackcount: 15 //須要返回數據的個數app
其餘參數:xss
根據接口的所需參數函數
實現原理:fetch
當第一次訪問接口時,傳遞2個必備參數(第1次加載,須要返回數據的個數爲15個),和其餘參數(須要搜索的字符串)給後臺,後臺返回第一次數據過來。在請求成功的的回調函數中,判斷返回的數據是否>0,是,則取出數據,渲染視圖層,並把「上拉加載」顯示在列表底部;否,則沒有數據可取,並把「沒有更多」顯示在列表底部,同時把「上拉加載」隱藏掉。flex
當用戶已經滾動到列表底部(這裏使用到小程序提供的scroll-view組件的bindscrolltolower事件),觸發bindscrolltolower事件,參數pageindex+1,再把2個必備參數(第2次加載,須要返回數據的個數爲15個)和其餘參數(須要搜索的字符串)給後臺,後臺把其他的數據返回給前臺,前臺在原來數據的基礎上添加數據。ui
示例:
wxml:
1 <view class="search"> 2 <view class="search-bar"> 3 <view class="search-wrap"> 4 <icon type="search" size="16" class="icon-search" /> 5 <input type="text" placeholder="請輸入搜索內容" class="search-input" name="searchKeyword" bindinput="bindKeywordInput" value="{{searchKeyword}}" /> 6 </view> 7 <view class="search-cancel" bindtap="keywordSearch">搜索</view> 8 </view> 9 <view class="search-result"> 10 <scroll-view scroll-y="true" bindscrolltolower="searchScrollLower"> 11 <view class="result-item" wx:for="{{searchSongList}}" wx:key="unique" data-data="{{item}}" > 12 <view class="icon{{item.isonly=='0' ? ' nocopyright' : ''}}"></view> 13 <text class="title">{{item.songname}}</text> 14 <view class="subtitle"> 15 <text wx:for="{{item.singer}}" wx:key="unique">{{item.name}}</text> 16 </view> 17 </view> 18 <view class="loading" hidden="{{!searchLoading}}">正在載入更多...</view> 19 <view class="loading complete" hidden="{{!searchLoadingComplete}}">已加載所有</view> 20 </scroll-view> 21 </view> 22 </view>
js:
1 var util = require('../../utils/util.js') 2 Page({ 3 data: { 4 searchKeyword: '', //須要搜索的字符 5 searchSongList: [], //放置返回數據的數組 6 isFromSearch: true, // 用於判斷searchSongList數組是否是空數組,默認true,空的數組 7 searchPageNum: 1, // 設置加載的第幾回,默認是第一次 8 callbackcount: 15, //返回數據的個數 9 searchLoading: false, //"上拉加載"的變量,默認false,隱藏 10 searchLoadingComplete: false //「沒有數據」的變量,默認false,隱藏 11 }, 12 //輸入框事件,每輸入一個字符,就會觸發一次 13 bindKeywordInput: function(e){ 14 console.log("輸入框事件") 15 this.setData({ 16 searchKeyword: e.detail.value 17 }) 18 }, 19 //搜索,訪問網絡 20 fetchSearchList: function(){ 21 let that = this; 22 let searchKeyword = that.data.searchKeyword,//輸入框字符串做爲參數 23 searchPageNum = that.data.searchPageNum,//把第幾回加載次數做爲參數 24 callbackcount =that.data.callbackcount; //返回數據的個數 25 //訪問網絡 26 util.getSearchMusic(searchKeyword, searchPageNum,callbackcount, function(data){ 27 console.log(data) 28 //判斷是否有數據,有則取數據 29 if(data.data.song.curnum != 0){ 30 let searchList = []; 31 //若是isFromSearch是true從data中取出數據,不然先從原來的數據繼續添加 32 that.data.isFromSearch ? searchList=data.data.song.list : searchList=that.data.searchSongList.concat(data.data.song.list) 33 that.setData({ 34 searchSongList: searchList, //獲取數據數組 35 zhida: data.data.zhida, //存放歌手屬性的對象 36 searchLoading: true //把"上拉加載"的變量設爲false,顯示 37 }); 38 //沒有數據了,把「沒有數據」顯示,把「上拉加載」隱藏 39 }else{ 40 that.setData({ 41 searchLoadingComplete: true, //把「沒有數據」設爲true,顯示 42 searchLoading: false //把"上拉加載"的變量設爲false,隱藏 43 }); 44 } 45 }) 46 }, 47 //點擊搜索按鈕,觸發事件 48 keywordSearch: function(e){ 49 this.setData({ 50 searchPageNum: 1, //第一次加載,設置1 51 searchSongList:[], //放置返回數據的數組,設爲空 52 isFromSearch: true, //第一次加載,設置true 53 searchLoading: true, //把"上拉加載"的變量設爲true,顯示 54 searchLoadingComplete:false //把「沒有數據」設爲false,隱藏 55 }) 56 this.fetchSearchList(); 57 }, 58 //滾動到底部觸發事件 59 searchScrollLower: function(){ 60 let that = this; 61 if(that.data.searchLoading && !that.data.searchLoadingComplete){ 62 that.setData({ 63 searchPageNum: that.data.searchPageNum+1, //每次觸發上拉事件,把searchPageNum+1 64 isFromSearch: false //觸發到上拉事件,把isFromSearch設爲爲false 65 }); 66 that.fetchSearchList(); 67 } 68 } 69 })
util.js:
1 function getSearchMusic(keyword, pageindex, callbackcount, callback){ 2 wx.request({ 3 url: 'https://c.y.qq.com/soso/fcgi-bin/search_for_qq_cp', 4 data: { 5 g_tk: 5381, 6 uin: 0, 7 format: 'json', 8 inCharset: 'utf-8', 9 outCharset: 'utf-8', 10 notice: 0, 11 platform: 'h5', 12 needNewCode: 1, 13 w: keyword, 14 zhidaqu: 1, 15 catZhida: 1, 16 t: 0, 17 flag: 1, 18 ie: 'utf-8', 19 sem: 1, 20 aggr: 0, 21 perpage: 20, 22 n: callbackcount, //返回數據的個數 23 p: pageindex, 24 remoteplace: 'txt.mqq.all', 25 _: Date.now() 26 }, 27 method: 'GET', 28 header: {'content-Type': 'application/json'}, 29 success: function(res){ 30 if(res.statusCode == 200){ 31 callback(res.data); 32 } 33 } 34 }) 35 } 36 37 module.exports = { 38 getSearchMusic: getSearchMusic 39 }
wxss:
1 page{ 2 display: flex; 3 flex-direction: column; 4 height: 100%; 5 } 6 7 /*搜索*/ 8 .search{ 9 flex: auto; 10 display: flex; 11 flex-direction: column; 12 background: #fff; 13 } 14 .search-bar{ 15 flex: none; 16 display: flex; 17 align-items: center; 18 justify-content: space-between; 19 padding: 20rpx; 20 background: #f4f4f4; 21 } 22 .search-wrap{ 23 position: relative; 24 flex: auto; 25 display: flex; 26 align-items: center; 27 height: 80rpx; 28 padding: 0 20rpx; 29 background: #fff; 30 border-radius: 6rpx; 31 } 32 .search-wrap .icon-search{ 33 margin-right: 10rpx; 34 } 35 .search-wrap .search-input{ 36 flex: auto; 37 font-size: 28rpx; 38 } 39 .search-cancel{ 40 padding: 0 20rpx; 41 font-size: 28rpx; 42 } 43 44 /*搜索結果*/ 45 .search-result{ 46 flex: auto; 47 position: relative; 48 } 49 .search-result scroll-view{ 50 position: absolute; 51 bottom: 0; 52 left: 0; 53 right: 0; 54 top: 0; 55 } 56 .result-item{ 57 position: relative; 58 display: flex; 59 flex-direction: column; 60 padding: 20rpx 0 20rpx 110rpx; 61 overflow: hidden; 62 border-bottom: 2rpx solid #e5e5e5; 63 } 64 65 .result-item .media{ 66 position: absolute; 67 left: 16rpx; 68 top: 16rpx; 69 width: 80rpx; 70 height: 80rpx; 71 border-radius: 999rpx; 72 } 73 .result-item .title, 74 .result-item .subtitle{ 75 overflow: hidden; 76 text-overflow: ellipsis; 77 white-space: nowrap; 78 line-height: 36rpx; 79 } 80 .result-item .title{ 81 margin-bottom: 4rpx; 82 color: #000; 83 } 84 .result-item .subtitle{ 85 color: #808080; 86 font-size: 24rpx; 87 } 88 .result-item:first-child .subtitle text{ 89 margin-right: 20rpx; 90 } 91 .result-item:not(:first-child) .subtitle text:not(:first-child):before{ 92 content: '/'; 93 margin: 0 8rpx; 94 } 95 .loading{ 96 padding: 10rpx; 97 text-align: center; 98 } 99 .loading:before{ 100 display: inline-block; 101 margin-right: 5rpx; 102 vertical-align: middle; 103 content: ''; 104 width: 40rpx; 105 height: 40rpx; 106 background: url(../../images/icon-loading.png) no-repeat; 107 background-size: contain; 108 animation: rotate 1s linear infinite; 109 } 110 .loading.complete:before{ 111 display: none; 112 }