uniapp mixin 使用

uniapp mixin 使用

创建 ListMoreDataMixin

// 由于没有超类的限制这里要判断下
function ____checkGetData(context) {
  if (!context.getData || typeof context.getData !== "function") {
    throw new Error("使用[ListMoreDataMixin]必须实现getData函数");
  }
}

export const ListMoreDataMixin = {
  data() {
    return {
      listData: [], // 数据列表
      page: 1, // 1
      limit: 10,
      isLoading: false, // 是否在加载数据
      isRefresh: false, // 下拉刷新

      autoInitListData: true,
    };
  },
  methods: {
    // 初始化数据
    async initData() {
      ____checkGetData(this);
      this.page = 1;
      this.isLoading = true;
      const data = await this.getData();
      this.listData = data;
      this.isLoading = false;
    },

    // 上拉加载更多
    async loadMore() {
      ____checkGetData(this);
      this.isLoading = true;
      this.page += 1;

      const data = await this.getData();

      // 没有更多了
      if (!data || !data.length) {
        this.page--;
        if (this.notMoreData) {
          this.notMoreData?.();
        } else {
          uni.showToast({
            title: "到底了...",
            icon: "none",
          });
        }
      }

      this.listData = [...this.listData, ...data];
      this.isLoading = false;
    },

    // 下拉刷新
    async onRefresh(done) {
      ____checkGetData(this);
      this.isRefresh = true;
      await this.initData();
      this.isRefresh = false;
      if (done && typeof done === "function") done();
    },
  },
  mounted() {
    if (this.autoInitListData) this.initData();
  },
};

在组件中使用

<template>
    <scroll-view
      v-if="listData.length"
      :scroll-y="true"
      :scroll-with-animation="true"
      :refresher-enabled="true"
      :refresher-triggered="isRefresh"
      @refresherrefresh="onRefresh"
      @scrolltolower="loadMore"
    >
      <list-item v-for="item of listData" :key="item.id" :data="item" />
    </scroll-view>
</template>

<script>
import { ListMoreDataMixin } from 'list-more-data-mixin.js';

export default {
  mixins: [ListMoreDataMixin],
  methods: {
    // 必须实现
    async getData() {
      return this.api.get("/api/xxx", { page: this.page, limit: this.limit });
    },
  }
};
</script>

长列表

看这里

创建 LongListMoreDataMixin

// 由于没有超类的限制这里要判断下
function ____checkGetData(context) {
  if (!context.getData || typeof context.getData !== "function") {
    throw new Error("使用[ListMoreDataMixin]必须实现getData函数");
  }
}

export const LongListMoreDataMixin = (manage) => {
  const PAGE = 1;
  const LIMIT = 20;
  return {
    data() {
      return {
        sections: [],
        page: PAGE,
        limit: LIMIT,
        isLoading: false, // 是否在加载数据
        isRefresh: false, // 下拉刷新

        autoInitListData: true,
      };
    },
    methods: {
      // 初始化数据
      async initData() {
        ____checkGetData(this);
        this.page = PAGE;
        this.isLoading = true;
        this._list = manage.clear();
        this.sections = [];
        const data = await this.getData();
        
        this._appendData(data);
        this.isLoading = false;
      },

      // 上拉加载更多
      async loadMore() {
        ____checkGetData(this);
        this.isLoading = true;
        this.page += 1;

        const data = await this.getData();

        // 没有更多了
        if (!data || !data.length) {
          this.page--;
          if (this.notMoreData) {
            this.notMoreData?.();
          } else {
            uni.showToast({
              title: "到底了...",
              icon: "none",
            });
          }
        }

        this._appendData(data);
        this.isLoading = false;
      },

      // 下拉刷新
      async onRefresh(done) {
        ____checkGetData(this);
        this.isRefresh = true;
        await this.initData();
        this.isRefresh = false;
        if (done && typeof done === "function") done();
      },

      _addSection(data) {
        if (!data.length) return;
        this.sections.push({
          begin: this._list.length - data.length,
          end: this._list.length
        })
      },
      
      _appendData(data) {
        this._list.push(...data);
        this._addSection(data);
      }
    },
    mounted() {
      if (this.autoInitListData) this.initData();
    },
  };
}

组件中将你的列表分段

<template>
  <view>
    <my-section v-for="(item, index) in sections" :key="index" :section="item"></my-section>
  </view>
</template>

<script>
import manage from './list-manage';
import { LongListMoreDataMixin } from './LongListMoreDataMixin.js';

export default {
  mixins: [LongListMoreDataMixin(manage)],
  onPullDownRefresh() {
    this.onRefresh(() => {
      uni.stopPullDownRefresh();
    });
  },
  onReachBottom() {
    this.loadMore();
  },
  methods: {
    getData() {
      return new Promise(_res => {
        this.request({
          page: this.page,
          size: this.limit,
          success: res => {
            _res(res);
          }
        });
      });
    }
  }
};
</script>

my-section:

<template>
  <my-item v-for="(item, index) in list" :key="index" :data="item"></my-item>
</template>

<script>
import manage from './list-manage';

export default {
  props: ['section'],
  data() {
    return {
      list: []
    };
  },
  created() {
    this.list = manage.getSection(this.section);
  }
};
</script>

<style></style>

list-manage.js 中导出静态列表,和一些管理函数

const manage = {
  list: [],
  clear() {
    return manage.list = []
  },
  getSection(section) {
    return manage.list.slice(section.begin, section.end);
  }
}

export default manage;