第五章 “我要点爆”微信小程序云开发实例之从云端获取数据制作首页
下面我们来实现从云端获取数据,完成首页世界页面index的制作,首页分为4个数据列表导航页面,页面具体内容如下:
推荐:为用户推荐最新的点爆信息,它包含文本点爆内容和语音点爆内容。
文爆:筛选出文字点爆内容,只显示文字点爆内容。
音爆:筛选出语音点爆内容,只显示语音点爆内容。
爆榜:将点爆内容取出前20名进入排行。
【实现页面内数据列表的滚动和导航切换后,每个导航下数据列表都在顶部】
由于我们使用的头部导航栏是通过数据绑定在同一页面进行切换,所以当一个页面内数据列表向下滚动后,切换导航后页面的scroolTop值已经改变,所以当从一个滚动过的导航数据列表切换到到另一个导航数据列表时,不能保持当前导航下数据列表在顶部,而会包含一个scroolTop值,下面我们就来实现导航切换后,数据列表为顶部位置。
在wxml中使用可滚动试图区域scrool-view组件做为数据列表的容器,wxml中设置组件scroll-y="true"为y轴滚动,同时通过数据绑定scroll-top="{{scrollTop}}"设置竖向滚动条位置,设置组件绝对定位样式。
<scroll-view scroll-y="true" scroll-top="{{scrollTop}}" style="position:absolute; top:0; left:0; right:0; bottom:0;">
</scroll-view>
在js中,我们给scrollTop设置初值为0,让页面打开时滚动条就在顶部
data: {
scrollTop: 0,
}
在每一次导航切换时,都将scrollTop的值重新赋值为0,保证当前导航页面滚动条在顶部。
this.setData({
scrollTop: 0
})
【实现数据列表加载功能】
在组件中使用wx:for进行控制属性绑定一个数组,使用数组中各项的数据重复渲染该组件。
wx:for-item制定数组当前元素变量名,将数据的id赋值给wx:key以便提高渲染效率,同时将数据的id赋值给id属性,方便跳转到详情页面。
block标签,使用block标签来进行条件渲染,
<view class="content_item" wx:for="{{tarray}}"
wx:for-item="recommend" wx:key="{{recommend._id}}" id="{{recommend._id}}">
<block wx:if="{{recommend.text}}">
<text>{{recommend.text}}</text>
</block>
</view>
当然,我们也可以直接在组件中使用wx:if,例如在文爆中控制只显示文本类爆文
<view class="content_item" bindtap="goopen" wx:for="{{tarray}}"
wx:for-item="textbao" wx:key="{{textbao._id}}" id="{{textbao.detailId}}"
wx:if="{{textbao.text}}">
</view>
在data中初始化一个数组tarray,用于保存从数据库中获取到的推荐爆文数据
data: {
tarray: [],
}
orderBy指定按照时间逆序排序,limit指定查询结果集数量上限为20,即最开始只从数据库获取20条数据,通过上拉加载来获取更多的数据
// 推荐数据
db.collection('bao').orderBy('time', 'desc').limit(20)
.get();
上拉加载,设置一个lnum1变量来记录当前页面有多少条数据,每次上拉获取10条数据,使用skip实现上拉加载更多,skip指定返回结果从指定序列后的结果开始返回
// 推荐数据
db.collection('bao').orderBy('wtime', 'desc').skip(lnum1).limit(10)
.get();
index.wxml完整代码
<!--index.wxml-->
<view class="header">
<label>
<input type="text" bindtap="search"/>
</label>
<view class="navbar">
<text class="item {{currentTab==index ? 'active' : ''}}" wx:for="{{navber}}"
data-index="{{index}}" wx:key="unique" bindtap="navbarTap">{{item}}</text>
</view>
</view>
<scroll-view class="content" scroll-y="true" scroll-top="{{scrollTop}}"
bindscrolltolower="thebottom" style="position:absolute; top:0; left:0; right:0; bottom:0;">
<view class="content_box">
<!-- 推荐数据列表 -->
<view class="recommend {{currentTab==0 ? 'show' : 'hide'}}">
<view class="content_item" bindtap="goopen" wx:for="{{tarray}}"
wx:for-item="recommend" wx:key="{{recommend._id}}" id="{{recommend._id}}">
<view class="citem_left">
<image src="/images/tou1.png"></image>
</view>
<block wx:if="{{recommend.text}}">
<view class="citem_mid">
<text>{{recommend.text}}</text>
<text>点爆方式:</text><text>{{recommend.wway}}</text>
</view>
<view class="citem_right">
<image src="/images/re.png"></image>
<text>{{recommend.temperature}}</text>
</view>
</block>
<block wx:if="{{recommend.filename}}">
<view class="citem_mid">
<image src="/images/yuyin.png"></image>
<text>点爆方式:</text><text>{{recommend.yway}}</text>
</view>
<view class="citem_right">
<image src="/images/re.png"></image>
<text>{{recommend.temperature}}</text>
</view>
</block>
</view>
</view>
<!-- 文爆 -->
<view class="textbao {{currentTab==1 ? 'show' : 'hide'}}">
<view class="content_item" bindtap="goopen" wx:for="{{tarray}}"
wx:for-item="textbao" wx:key="{{textbao._id}}" id="{{textbao.detailId}}" wx:if="{{textbao.text}}">
<view class="citem_left">
<image src="/images/tou1.png"></image>
</view>
<view class="citem_mid">
<text>{{textbao.text}}</text>
<text>点爆方式:</text><text>{{textbao.wway}}</text>
</view>
<view class="citem_right">
<image src="/images/re.png"></image>
<text>{{textbao.temperature}}</text>
</view>
</view>
</view>
<!-- 音爆 -->
<view class="voicebao {{currentTab==2 ? 'show' : 'hide'}}">
<view class="content_item" bindtap="goopen" wx:for="{{tarray}}"
wx:for-item="voicebao" wx:key="{{voicebao._id}}" id="{{voicebao.detailId}}" wx:if="{{voicebao.filename}}">
<view class="citem_left">
<image src="/images/tou1.png"></image>
</view>
<view class="citem_mid">
<image src="/images/yuyin.png"></image>
<text>点爆方式:</text><text>{{voicebao.yway}}</text>
</view>
<view class="citem_right">
<image src="/images/re.png"></image>
<text>{{voicebao.temperature}}</text>
</view>
</view>
</view>
<!-- 爆榜 -->
<view class="rankings {{currentTab==3 ? 'show' : 'hide'}}">
<view class="content_item" bindtap="goopen" wx:for="{{barray}}"
wx:for-item="rankings" wx:key="{{rankings._id}}" id="{{rankings._id}}">
<view class="number">
{{index+1}}
</view>
<view class="citem_left">
<image src="/images/tou1.png"></image>
</view>
<block wx:if="{{rankings.text}}">
<view class="citem_mid">
<text>{{rankings.text}}</text>
<text>点爆方式:</text><text>{{rankings.wway}}</text>
</view>
<view class="citem_right">
<image src="/images/re.png"></image>
<text>{{rankings.temperature}}</text>
</view>
</block>
<block wx:if="{{rankings.filename}}">
<view class="citem_mid">
<image src="/images/yuyin.png"></image>
<text>点爆方式:</text><text>{{rankings.yway}}</text>
</view>
<view class="citem_right">
<image src="/images/re.png"></image>
<text>{{rankings.temperature}}</text>
</view>
</block>
</view>
</view>
</view>
</scroll-view>
index.js完整代码
//index.js
//获取应用实例
const app = getApp()
Page({
data: {
navber: ['推荐', '文爆', '音爆', '爆榜'],
currentTab: 0,
tarray: [],
barray: [],
lnum1: 20,//记录当前已有数据数量
stext: '',
scrollTop: 0,
},
//上导航切换
navbarTap: function (e) {
this.setData({
scrollTop: 0
})
this.setData({
currentTab: e.currentTarget.dataset.index
})
},
search: function (e) {
wx.navigateTo({
url: '../search/search'
})
},
onLoad: function () {
wx.showLoading({
title: '加载中',
mask: true
})
const db = wx.cloud.database()
// 推荐数据
db.collection('bao').orderBy('time', 'desc').limit(20)
.get({
success: res => {
this.setData({
tarray: res.data
})
}
});
// 排行数据
db.collection('bao').orderBy('temperature', 'desc').limit(20)
.get({
success: res => {
this.setData({
barray: res.data
})
}
});
//模拟加载
setTimeout(function () {
wx.hideLoading()
}, 1500);
},
goopen: function (e) {
//获取当前内容的标识id,保存,方便进入查询
var id = e.currentTarget.id
wx.setStorageSync('id', id)
wx.navigateTo({
url: '../detail/detail',
});
},
//下拉刷新
onPullDownRefresh: function () {
wx.showNavigationBarLoading() //在标题栏中显示加载
wx.showLoading({
title: '加载中',
mask: true
})
const db = wx.cloud.database()
// 推荐数据
db.collection('bao').orderBy('time', 'desc').limit(20)
.get({
success: res => {
this.setData({
tarray: res.data
})
}
});
// 排行数据
db.collection('bao').orderBy('temperature', 'desc').limit(20)
.get({
success: res => {
this.setData({
barray: res.data
})
}
});
//模拟加载
setTimeout(function () {
// complete
wx.hideNavigationBarLoading() //完成停止加载
wx.stopPullDownRefresh() //停止下拉刷新
wx.hideLoading()
}, 1500);
},
//上拉加载
thebottom: function () {
var lnum1 = this.data.lnum1
const db = wx.cloud.database()
if (this.data.currentTab == 0) {
// 显示加载图标
wx.showLoading({
title: '玩命加载中',
})
// 推荐数据
db.collection('bao').orderBy('wtime', 'desc').skip(lnum1).limit(10)
.get({
success: res => {
this.setData({
tarray: this.data.tarray.concat(res.data),
lnum1: lnum1 + 10
})
// 隐藏加载框
wx.hideLoading()
}
});
}
}
})
运行效果图:
搜索框搜索页面的实现
app.json中加入search页面路径,编写搜索页面样式
search.wxml
<view class="header">
<label>
<input type="text" bindconfirm="search" bindinput="content"
confirm-type="search" focus="true"/>
<icon type="search" size="25" bindtap="search"/>
</label>
</view>
<view class="content">
<text class="nohave {{bol ? 'show' : 'hide'}}">你搜的什么吖,我莫得!</text>
<view class="searchArray">
<view class="content_item" bindtap="goopen" wx:for="{{tarray}}"
wx:for-item="searchArray" wx:key="{{searchArray._id}}" id="{{searchArray._id}}">
<view class="citem_left">
<image src="/images/tou1.png"></image>
</view>
<block wx:if="{{searchArray.text}}">
<view class="citem_mid">
<text>{{searchArray.text}}</text>
<text>点爆方式:</text><text>{{searchArray.wway}}</text>
</view>
<view class="citem_right">
<image src="/images/re.png"></image>
<text>{{searchArray.temperature}}</text>
</view>
</block>
<block wx:if="{{searchArray.filename}}">
<view class="citem_mid">
<image src="/images/yuyin.png"></image>
<text>点爆方式:</text><text>{{searchArray.yway}}</text>
</view>
<view class="citem_right">
<image src="/images/re.png"></image>
<text>{{searchArray.temperature}}</text>
</view>
</block>
</view>
</view>
</view>
db.RegExp介绍:数据库支持正则表达式查询,开发者可以在查询语句中使用 JavaScript 原生正则对象或使用 db.RegExp 方法来构造正则对象然后进行字符串匹配。在查询条件中对一个字段进行正则匹配即要求该字段的值可以被给定的正则表达式匹配,注意正则表达式不可用于 db.command 内(如 db.command.in)。
使用db.RegExp方法构造正则对象然后进行字符串匹配,通过在对bao集合中text内容进行查询时,给text赋值一个db.RegExp正则对象,这样就实现了对text的模糊查询。
db.collection('bao').where({
//使用正则查询,实现对搜索的模糊查询
text: db.RegExp({
regexp: value,
//从搜索栏中获取的value作为规则进行匹配。
options: 'im',
//大小写不区分
})
}).get()
search.js完整代码
// pages/search/search.js
Page({
data: {
tarray: [],
stext: '',
bol: false,
},
search: function () {
wx.showLoading({
title: '玩命加载中',
})
this.setData({
tarray: []
})
//连接数据库
const db = wx.cloud.database()
var that = this
var value = this.data.stext
db.collection('bao').where({
//使用正则查询,实现对搜索的模糊查询
text: db.RegExp({
regexp: value,
//从搜索栏中获取的value作为规则进行匹配。
options: 'im',
//大小写不区分
})
}).get({
success: res => {
console.log(res)
if (res.data.length == 0) {
that.setData({
bol: true
})
} else {
that.setData({
tarray: res.data
})
}
wx.hideLoading()
}
})
},
content: function (e) {
this.setData({
stext: e.detail.value
})
},
goopen: function (e) {
//获取当前内容的标识id,保存,方便进入查询
var id = e.currentTarget.id
wx.setStorageSync('id', id)
wx.navigateTo({
url: '../detail/detail',
});
},
})
运行效果图
至此,首页就制作完成了,可以说小程序的主体已经差不多了,云开发的便利我们也都尝试了。那么大家就快进行实践吧!