#### 组件名称
feed

#### 解释：
feed 信息流

#### 属性说明：
|属性名 | 类型 | 必填 | 默认值 |说明 |
|---|---|---|---|---|
|theme |String |false|-|主题配置，默认浅色；深色主题请指定dark|
|pullToRefresh |Boolean |false|false|是否开启手势下拉刷新; 默认只能通过组件api调起|
|lowerThreshold |Number |false|150px（设备上的px）|触发scrolltolower事件的阈值|
|text |String |false|建议最多显示18个汉字，超出内容截断|加载成功时的展示话术|
|onrefresh |EventHandle |false||手势滑动触发加载时，响应该onRefresh事件; 通过调用api加载，不会触发该事件|
|startRefresh |EventHandle |false||手动调用该api，触发加载|
|stopRefresh |EventHandle |false||手动调用该api，停止加载，并弹出加载提示（对应属性text）；可使用await等待关闭动画结束|
|closeLoading |EventHandle |false||手动调用该api，立即关闭加载，不弹出加载提示；例如接口异常，建义直接关闭加载|

#### 代码示例
swan:
```
<tabs
        tabs-background-color="#3388ff"
        tabs-underline-color = "#fff"
        tabs-inactive-text-color="#fff"
        tabs-active-text-color="#fff"
        bindtabchange="tabChange"
        active-name="{{activeName}}">
        <tab-item
            s-for="item in ['下拉刷新', '自动刷新']"
            name="{{item}}"
            label="{{item}}"
        />
    </tabs>
    <!-- 下拉刷新 -->
    <zw-feed
        s-if="{{activeName === '下拉刷新'}}"
        class="zw-feed pull-down-refresh"
        pull-to-refresh
        bind:onrefresh="onRefresh"
        bind:scrolltolower="scrollToLower"
        text="{{text}}"
    >
        <list list="{{list}}"></list>
        <smt-spin status="{{status}}" bind:tap="reload"></smt-spin>
    </zw-feed>

    <!-- 自动刷新 -->
    <zw-feed
        s-elif="{{activeName === '自动刷新'}}"
        class="zw-feed auto-refresh"
        text="{{text}}"
    >
        <list list="{{list}}"></list>
    </zw-feed>
```
js:
```
import {selComponent} from 'yourpath/common/utils/index';
import {syncSetData} from 'yourpath/mock/base';

/* eslint-disable babel/new-cap */
Page({
/* eslint-enable babel/new-cap */
    data: {
        activeName: '下拉刷新',
        list: Array.from({length: 15}, (_, i) => i),
        text: '',
        status: 1
    },

    tabChange({detail}) {
        console.log(detail);
        this.setData({
            activeName: detail.name
        },
        () => this.autoRefresh(detail.name));
    },

    /**
     * 请求时长1200ms
     */
    async fetchData(ms = 1200) {
        const empty = Math.random() > .7;
        const fail = Math.random() > .9;
        const data = {
            code: fail ? -1 : 0,
            data: fail || empty ? null : Array.from({length: Math.random() * 10 + 10 | 0}, (_, i) => i)
        };
        return new Promise(r => setTimeout(() => r(data), ms));
    },

    async onRefresh() {
        console.log('触发 onRefresh');
        const refresh = await selComponent(this, '.pull-down-refresh');
        const {code, data: list} = await this.fetchData();
        if (code !== 0) {
            swan.showToast({title: '网络错误', mask: true, icon: 'none'});
            refresh.closeLoading();
            return;
        }
        await syncSetData(this, {
            status: 1,
            list: list || this.data.list,
            text: list ? `本次共加载${list.length}条数据！` : '暂时没有更新，休息一下'
        });
        refresh.stopRefresh();
    },

    async autoRefresh() {
        if (this.data.activeName === '自动刷新') {
            const clkRefresh = await selComponent(this, '.auto-refresh');
            const autoLoad = async () => {
                clkRefresh.startRefresh();
                const {code, data: list} = await this.fetchData();
                if (code !== 0) {
                    swan.showToast({title: '网络错误', mask: true, icon: 'none'});
                    clkRefresh.closeLoading();
                    return;
                }
                await syncSetData(this, {
                    status: 0,
                    list: list || this.data.list,
                    text: list ? `本次共加载${list.length}条数据！` : '暂时没有更新，休息一下'
                });
                await new Promise(r => setTimeout(r, 1500)); // 1500ms 之后再关闭： 手动关闭不需要等小球转3圈
                await clkRefresh.stopRefresh();
                await new Promise(r => setTimeout(r, 500)); // 加载完一轮等500ms
                this.data.activeName === '自动刷新' && await autoLoad();
            };
            autoLoad();
        }
    },

    async scrollToLower() {
        const {code, data: list} = await this.fetchData();
        const fail = code !== 0;
        const end = !list;
        if (fail || end) {
            this.setData({
                status: fail ? 3 : 2
            });
            return;
        }
        await syncSetData(this, {
            list: list.concat(this.data.list || [])
        });
    },

    async reload() {
        if (this.data.status !== 0 && this.data.status !== 3) {
            return;
        }
        await syncSetData(this, {status: 1});
        this.scrollToLower();
    }
});

```
css:
```
.zw-feed {
    display: block;
    height: calc(100vh - 40px);
}
```
