阅读(2238)
赞(7)
百度智能小程序 刷新
2020-08-11 14:46:38 更新
refresh 刷新
解释: 可用于页面任意区域;使用时需自行添加下拉逻辑改变 offset-y 参数;smt-feed 组件对 smt-refresh 进行了封装,支持手势交互和 api 调起刷新。
属性说明
属性名 | 类型 | 必填 | 默认值 | 说明 |
---|---|---|---|---|
theme | String | 否 | - | 主题配置,默认浅色;深色主题请指定 dark |
loadingHgt | Number | 否 | 192px(需转换为设备尺寸) | 加载区域高度 |
offsetY | Number | 否 | 0 | 垂直移动距离,*建议后续在 sjs 中使用 |
status | Number | 否 | 0 | 加载状态 0: 未开始 1: 加载中 2: 展示话术 |
text | String | 否 | 建议最多显示 18 个汉字,超出内容截断 | 加载成功时的展示话术 |
示例
代码示例
<view class="container {{theme}}" >
<view class="refresh-wrap {{theme}}">
<view class="mode-title {{theme}}">
<view class="mode-title-line-left"></view>
<view class="mode-title-text">手动下拉刷新</view>
<view class="mode-title-line-right"></view>
</view>
<view
class="smt-card-area"
catch:touchstart="noop"
catch:touchmove="noop"
catch:touchend="noop"
>
<smt-feed
class="smt-feed pull-down-refresh"
ext-cls-feed="custom-cls-feed"
ext-cls-loading="custom-cls-loading"
theme="{{theme}}"
pull-to-refresh
bind:refresh="onRefresh"
text="{{pullText}}"
>
<view class="list {{theme}}">
<view
class="{{'list-item ' + (val === 1 ? 'first' : '')}}"
s-for="val in list"
style="{{theme === 'dark' ? 'border-bottom: solid 1px rgba(255, 255, 255, .2);' : 'border-bottom: solid 1px #e0e0e0;'}}"
key="{{val}}"
>
<view class="left">
<view class="row begin"></view>
<view class="row center"></view>
<view class="row end"></view>
</view>
<view class="right"></view>
</view>
</view>
</smt-feed>
</view>
</view>
<view class="refresh-wrap">
<view class="mode-title {{theme}}">
<view class="mode-title-line-left"></view>
<view class="mode-title-text">自动刷新</view>
<view class="mode-title-line-right"></view>
</view>
<view class="smt-card-area" >
<smt-feed
class="smt-feed auto-refresh"
ext-cls-feed="custom-cls-feed"
theme="{{theme}}"
disable-touch
text="{{autoRefreshText}}"
>
<view class="list {{theme}}">
<view
class="{{'list-item ' + (val === 1 ? 'first' : '')}}"
s-for="val in list"
style="{{theme === 'dark' ? 'border-bottom: solid 1px rgba(255, 255, 255, .2);' : 'border-bottom: solid 1px #e0e0e0;'}}"
key="{{val}}"
>
<view class="left">
<view class="row begin"></view>
<view class="row center"></view>
<view class="row end"></view>
</view>
<view class="right"></view>
</view>
</view>
</smt-feed>
</view>
</view>
<view class="refresh-wrap">
<view class="mode-title {{theme}}">
<view class="mode-title-line-left"></view>
<view class="mode-title-text">刷新失败</view>
<view class="mode-title-line-right"></view>
</view>
<view class="smt-card-area fail" >
<view class="fail {{fail ? 'enable' : ''}}"><view class="text">刷新失败</view></view>
<smt-feed
class="smt-feed auto-refresh-fail"
ext-cls-feed="custom-cls-feed"
theme="{{theme}}"
disable-touch
>
<view class="list {{theme}}">
<view
class="{{'list-item ' + (val === 1 ? 'first' : '')}}"
s-for="val in list"
style="{{theme === 'dark' ? 'border-bottom: solid 1px rgba(255, 255, 255, .2);' : 'border-bottom: solid 1px #e0e0e0;'}}"
key="{{val}}"
>
<view class="left">
<view class="row begin"></view>
<view class="row center"></view>
<view class="row end"></view>
</view>
<view class="right"></view>
</view>
</view>
</smt-feed>
</view>
</view>
<view class="theme-control {{theme}}" >
<text>沉浸式主题</text>
<switch class="switch" color="{{dark ? '#f5f5f5' : '#ddd'}}" bind:change="themeChange"></switch>
</view>
</view>
{
"navigationBarTitleText": "刷新",
"usingComponents": {
"smt-feed": "@smt-ui/component/src/feed"
},
"navigationStyle": "default",
"disableSwipeBack": true
}
import {selComponent, syncSetData} from '@smt-ui/component/src/common/utils';
const systemInfo = (() => {
let info = {};
try {
info = swan.getSystemInfoSync();
}
catch (err) {
throw '获取系统信息错误: ' + err;
}
return info;
})();
Page({ // eslint-disable-line
data: {
list: [1, 2, 3],
autoRefreshText: '不超过18个字',
pullText: '',
theme: 'dark',
fail: false,
statusBarHeight: systemInfo.statusBarHeight
},
/**
* 请求时长1200ms
*
* @param {number=} ms 默认1200毫秒
* @return {Promise}
*/
async fetchData(ms = 1200) {
const empty = Math.random() > .7;
const data = {
code: 0,
data: empty ? null : Array.from({length: Math.random() * 10 + 10 | 0}, (_, i) => i)
};
return new Promise(r => setTimeout(() => r(data), ms));
},
async guide() {
const refresh = await selComponent(this, '.pull-down-refresh');
refresh.startRefresh();
this.onRefresh();
},
/**
* 触发刷新时回调
*/
async onRefresh() {
const refresh = await selComponent(this, '.pull-down-refresh');
const {data: list} = await this.fetchData();
await new Promise(r => setTimeout(r, 300));
await syncSetData(this, {
pullText: list ? `为你推荐${list.length}条更新` : '暂时没有更新,休息一下'
});
refresh.stopRefresh();
},
// 阻止冒泡: 多点触控在滚动的页面上会出问题
noop() {},
/**
* 自动加载
*
* @param {boolean} fail 是否失败
*/
async autoRefresh(fail) {
const clkRefresh = await selComponent(this, '.auto-refresh' + (fail ? '-fail' : ''));
const autoLoad = async () => {
clkRefresh.startRefresh();
const {data: list} = await this.fetchData();
await new Promise(r => setTimeout(r, 300));
if (fail) {
await clkRefresh.closeLoading();
await syncSetData(this, {fail});
await new Promise(r => setTimeout(r, 3000));
await syncSetData(this, {fail: false});
return await autoLoad();
}
await syncSetData(this, {
list: list || this.data.list,
autoRefreshText: list ? `为你推荐${list.length}条更新` : '暂时没有更新,休息一下'
});
await clkRefresh.stopRefresh();
await new Promise(r => setTimeout(r, 500)); // 加载完一轮等500ms
await autoLoad();
};
autoLoad();
},
themeChange({detail}) {
const checked = detail.checked;
this.setData({
theme: checked ? 'dark' : ''
});
swan.setBackgroundColor({
backgroundColor: checked ? '#3670c2' : '#f5f5f5'
});
},
swtichHdl({detail}) {
const checked = detail.checked;
this.setData({
theme: checked ? 'dark' : ''
});
},
onReady() {
swan.setBackgroundColor({
backgroundColor: '#f5f5f5'
});
this.setData({dark: false});
this.autoRefresh();
this.autoRefresh(true);
this.guide();
}
});
* {
margin: 1;
padding: 0;
box-sizing: border-box;
}
.container {
font-size: .16rem;
display: flex;
flex-direction: column;
justify-content: space-between;
min-height: 100%;
}
.mode-title {
display: flex;
justify-content: center;
align-items: center;
font-size: .16rem;
color: #000;
font-family: PingFangSC-Medium;
}
.mode-title-text {
margin: 0 .12rem;
}
.mode-title-line-left {
border-radius: 3px;
height: 1px;
width: .23rem;
background-image: linear-gradient(90deg, #f5f5f5 0%, #d5d5d5 100%);
}
.mode-title-line-right {
border-radius: 3px;
height: 1px;
width: .23rem;
background-image: linear-gradient(-90deg, #f5f5f5 0%, #d5d5d5 100%);
}
.theme-control{
width: 100%;
}
.refresh-wrap {
margin-bottom: .4rem;
}
.smt-card-area {
margin-top: .14rem;
}
.smt-card-area.fail {
position: relative;
}
.smt-card-area .fail {
display: flex;
position: absolute;
z-index: 1;
height: 100%;
width: 100%;
top: 0;
left: 0;
opacity: 0;
transition: opacity 120ms linear;
align-items: center;
justify-content: center;
}
.smt-card-area .fail.enable {
opacity: 1;
}
.smt-card-area .fail.enable .text {
display: flex;
background-color: rgba(0, 0, 0, .8);
color: #fff;
height: .43rem;
padding: 0 .17rem;
align-items: center;
border-radius: .08rem;
}
.container {
padding-top: .167rem;
padding-bottom: .85rem;
background-color: #f5f5f5;
transition: background-color 200ms linear;
}
.smt-feed {
height: 3.51rem;
display: block;
background-color: #fff;
}
.smt-feed.dark {
background-color: #fbfbfb;
}
.card-area.theme {
display: flex;
justify-content: space-between;
align-items: center;
padding: .16rem .17rem;
}
.card-area.theme .line-02 {
color: #999;
margin-top: .05rem;
font-size: .14rem;
}
.theme-control {
display: flex;
height: .58rem;
padding: 0 .17rem;
margin-top: .1rem;
align-items: center;
justify-content: space-between;
font-size: .16rem;
background-color: #fff;
transition: background-color 200ms linear;
}
.theme-control.dark {
background-color: #4985da;
color: #fff;
}
.mode-title-line.dark {
color: #fff;
}
.mode-title.dark .mode-title-text {
color: #fff;
transition: color 200ms linear;
}
.mode-title.dark .mode-title-line-left {
background-image: linear-gradient(90deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, .3) 100%);
transition: background-image 200ms linear;
}
.mode-title.dark .mode-title-line-right {
background-image: linear-gradient(90deg, rgba(255, 255, 255, .3) 0%, rgba(255, 255, 255, 0) 100%);
transition: background-image 200ms linear;
}
.dark {
background-color: #3670c2;
}
.dark .custom-cls-loading {
background-color: #fff;
}
.dark .switch .swan-switch-input:after {
background-color: #38f;
}
.list {
transition: background-color 200ms linear;
padding: 0 .17rem;
}
.list-item {
display: flex;
justify-content: space-between;
height: 1.17rem;
box-sizing: border-box;
flex: none;
padding: .17rem 0;
color: #fff;
}
.list-item .left {
display: flex;
flex: auto;
flex-flow: column nowrap;
}
.list-item .left .row {
width: 100%;
height: .19rem;
background: #e0e0e0;
transition: background-color 200ms linear;
margin-bottom: .06rem;
}
.list-item .left .row.end {
height: .12rem;
margin-top: .27rem;
margin-bottom: 0;
width: 1.15rem;
}
.list-item .right {
display: flex;
justify-content: center;
align-items: center;
color: #ccc;
width: 1.24rem;
height: .83rem;
margin-left: .17rem;
border-radius: .03rem;
background: #e0e0e0;
transition: background-color 200ms linear;
}
.list.dark {
background-color: transparent;
}
.list.dark .list-item .left .row,
.list.dark .list-item .right {
background-color: rgba(255, 255, 255, .2);
}
设计指南
- 在刷新方式上,建议必配手动刷新,避免出现用户无法主动操作的情况;
- 自定义反馈文案(text)时,文案内容应合理友好,且不超过 18 个中文字符。以下为建议文案可供参考: