阅读(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);
}

设计指南

  1. 在刷新方式上,建议必配手动刷新,避免出现用户无法主动操作的情况;
  2. 自定义反馈文案(text)时,文案内容应合理友好,且不超过 18 个中文字符。以下为建议文案可供参考: