加载数据:
说到列表,在Android 中大部分都是和数组或者list容器绑定。
小程序中也是这么个思想。但是可能数据表现形式有所不同。
所以先了解一下js中表示数据集合的数组。
js中的数组的表示方式是[ a, b, c],组内元素用 ,隔开。
声明方式
1.var cars = ["Saab", "Volvo", "BMW"];
2.var cars = new Array("Saab", "Volvo", "BMW");
一般都是用第一种。
用cars[0] 来表示第一个,和Java的语法一样。
//Arraytest.js
Page({
data: {
numberArray: [1, 2, 3, 4]
}
})
在js文件的data中定义了数组。
在wxml中
//ArrayTest.wxml
<!—- 遍历数组,并为数组中的每一个值创建一个switch开关 —->
<switch wx:for="{{numberArray}}"
style="display: block;"> {{item}} </switch>
组件用到了wx:for属性,也就是说这个组件绑定了一个数组,就是说数组中有几个元素,就会把这个组件渲染几个。内容item则指的是每个元素。
也就是说不出意外的话,上面的代码应该会显示4个开关。
那么如果item是对象的话,我们可以针对每个元素对象的某个属性{{item.attr}}进行展示。
<!--arraytest/arraytest.wxml-->
<switch style="display:block"
wx:for="{{numberArray}}">{{item}}</switch>
<view style="width:100%;height:1px;background-color:#999999;margin-top:30rpx;margin-bottom:30rpx"></view>
<!-- 展示对象数组中的name属性 -->
<button style="display:block"
wx:for="{{objectArray}}" wx:key="id">{{item.name}}</button>
// arraytest/arraytest.js
Page({
/**
* 页面的初始数据
*/
data: {
objectArray:[
{
id: 1,
name: "第一选择"
},
{
id: 2,
name: "第二选择"
},
{
id: 3,
name: "第三选择"
},
{
id: 4,
name: "第四选择"
},
],
numberArray:[1,2,3,4]
}
}
当我们修改了数组中某一项的数据时,布局中的列表会全部刷新吗?
不会,如果你设置了wx:key的话会把组件和这个数据通过key绑定。
设置key后,改变数组中的某一项之后,布局中会找到这一项的key然后去刷新列表中对应key的组件。
wx:key 的值以两种形式提供
- 字符串,代表在 for 循环的 array 中 item 的某个 property,该 property 的值需要是列表中唯一的字符串或数字,且不能动态改变。
- 保留关键字 *this 代表在 for 循环中的 item 本身,这种表示需要 item 本身是一个唯一的字符串或者数字。
如果组件绑定了数组,记得设置key,如果不设置key的话会收到警告。
下拉刷新
知道了列表的绑定数据,再来看下Android中列表经常用到的下拉顺新和加载更多。
如果这样的话,需要给列表包括一个组件scroll-view
https://developers.weixin.qq.com/miniprogram/dev/component/scroll-view.html
撸起袖子上代码
注释很重要,重要!!!
<!--scrollview/scrolltest.wxml-->
<view class="container">
<text style="flex:0">scrollview/scrolltest.wxml</text>
<!--
1.refresher-enabled 是否开启下拉刷新
2.refresher-default-style定义下拉刷新的loading小点点的颜色;
3.refresher-background 下拉区域的背景色。官网说默认白色,试验如果不设置的话是透明
4.refresher-triggered 设置当前的刷新状态。用于自动刷新或者关闭刷新时
5.bindrefresherrefresh 下拉刷新时触发的方法 2.10以后才可以用
6.bindrefresherrestore 下拉刷新被复位是,即下拉刷新完成的的触发方法
7.bindscrolltolower 滚动到底部的方法,可以用来监测上拉加载-->
<scroll-view class="scrollview-style" scroll-y="true"
bindscrolltoupper="onRefresh"
bindscrolltolower="onLoadMore"
refresher-enabled="{{true}}"
refresher-background="#FFFFFF"
refresher-triggered="{{refreshing}}"
bindrefresherrefresh="onRefresh"
bindscrolltolower="onLoadMore"
>
<text wx:for="{{attr}}" style="display:block;height:200rpx" wx:key="*this">{{item}}</text>
</scroll-view>
<!--<button type="primary">bottom</button>-->
</view>
样式文件
/* scrollview/scrolltest.wxss */
page{
height: 100%;
}
.container{
display: flex;
flex-direction: column;
height: 100%;
}
.scrollview-style{
width: 100%;
flex: 1;
background-color: red;
}
js文件
// scrollview/scrolltest.js
Page({
/**
* 页面的初始数据
*/
data: {
attr: ["item1", "item2", "item3", "item4", "item5", "item6", "item7", "item8", "item9", "item10"],
refreshing: false,
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
},
/**
* 下拉刷新
*/
onRefresh: function (e) {
setTimeout(() => {
// 设置3秒后停止刷新
this.setData({
refreshing: false,
})
}, 3000);
},
})
主要是最后那个方法。来控制下拉刷新,并控制3秒后,停止刷新。
最后的效果
上拉加载
先说坑:
当我兴冲冲的用scroll-view中的bindtoscrolllower属性来绑定了js中的方法后,却发现这条路根本行不通。每次scrollview滑动到底部并没有触发这个方法。
看了看官网是这样说明的
但是我们用的是flex来确定的他的高度,实际上scrollview会根据内容来自己计算出高度,而flex中的flexbasis属性默认为auto,在scrollview的height面前是不起作用的。所以scrollview的高度会认为是我们的10个item的总高度。当我们向上滑动时,其实是向上滑动的整个页面内容,而不是scrollview中的内容进行滚动,自然不会触发bindtoscrolllower方法。可以看下动画。会发现页面的其余组件也随着向上滚动而向上移出了页面。
可以看到页面上方的文本也被移出了页面。 也就是说我们滚动的是整个页面,而不是scrollview中的内容。
那么如何让scrollview的高度确定在 下方的区域,然后让其内容跟随滚动呢。
我查了大佬的做法。最后选择了这个文章中的方法。
https://blog.csdn.net/Abudula__/article/details/86667922
应用到我这个粗陋的demo中,解决思路就是这样的:
- 在scrollview外面套一层view让这个view的flex是1,即填满页面除去顶部的text的剩余空间。
- 将scrollview的position设置为absolute,并且填满view。
- view的position设置为relative,这个设置很重要。否则scrollview的absloute就会一直寻找position不是static的父组件填满。
解决办法:
看下最后的代码
<!--scrollview/scrolltest.wxml-->
<view class="container">
<text style="flex:0">scrollview/scrolltest.wxml</text>
<!-- position一定要设置 -->
<view style="flex:1;background-color:purple;position:relative">
<!--
1.refresher-enabled 是否开启下拉刷新
2.refresher-default-style定义下拉刷新的loading小点点的颜色;
3.refresher-background 下拉区域的背景色。官网说默认白色,试验如果不设置的话是透明
4.refresher-triggered 设置当前的刷新状态。用于自动刷新或者关闭刷新时
5.bindrefresherrefresh 下拉刷新时触发的方法 2.10以后才可以用
6.bindrefresherrestore 下拉刷新被复位是,即下拉刷新完成的的触发方法
7.bindscrolltolower 滚动到底部的方法,可以用来监测上拉加载-->
<scroll-view class="scrollview-style"
scroll-y="true"
refresher-enabled="{{true}}"
lower-threshold="{{10}}"
refresher-background="#FFFFFF"
refresher-triggered="{{refreshing}}"
bindrefresherrefresh="onRefresh"
bindscrolltolower="onLoadMore"
>
<text wx:for="{{attr}}" style="display:block;height:200rpx" wx:key="*this">{{item}}</text>
</scroll-view>
</view>
<!-- <button type="primary" style="flex:0 1 auto">bottom</button> -->
</view>
/* scrollview/scrolltest.wxss */
page {
height: 100%;
}
.container {
display: flex;
flex-direction: column;
height: 100%;
}
.scrollview-style {
background-color: red;
/* 填满父控件 */
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
js文件,只贴上了加载更多方法,其余地方和之前的js文件代码 一样。
加载更多的意思是在列表对应的数组每次多4个item,并更新到列表上。
/**
* 加载更多
*/
onLoadMore: function (e) {
console.log("onLoadMore");
let length = this.data.attr.length;
this.data.attr = this.data.attr.concat(["item" + (length + 1), "item" + (length + 2), "item" + (length + 3), "item" + (length + 4)]);
console.log(this.data.attr);
this.setData({
attr: this.data.attr,
})
}
这样,就完成了将scrollview的大小确定在剩余的空间内。
看下效果:
好了。至此,页面的加载数据,刷新和加载更多就写的差不多了。
如果对position不熟悉的地方,可以参考css教程中的关于【定位】的章节。
https://www.w3school.com.cn/css/css_positioning.asp
拜了拜。