159 lines
4.7 KiB
Vue
159 lines
4.7 KiB
Vue
<template>
|
||
<!-- top="xxx"下拉布局往下偏移,防止被悬浮菜单遮住 -->
|
||
<!-- 鸿蒙下不要用 v-if="isInit",会导致内层 mescroll 创建被严重延迟,先 onReady 后 inner created -->
|
||
<mescroll
|
||
:top="top"
|
||
:down="downOption"
|
||
:fixed="fixed"
|
||
:topbar="topbar"
|
||
:background="background"
|
||
:paddingBoth="paddingBoth"
|
||
@down="downCallback"
|
||
:up="upOption"
|
||
@up="upCallback"
|
||
@emptyclick="emptyClick"
|
||
@init="mescrollInit"
|
||
>
|
||
<!-- 数据列表 - 鸿蒙下用 key 强制重建 slot DOM,绕过 ArkUI slot 响应式失效问题 -->
|
||
<view :key="listSlotKey">
|
||
<slot name="list"></slot>
|
||
</view>
|
||
</mescroll>
|
||
</template>
|
||
|
||
<script>
|
||
import Mescroll from './mescroll-uni.vue';
|
||
export default {
|
||
components: {
|
||
Mescroll
|
||
},
|
||
data() {
|
||
return {
|
||
mescroll: null, //mescroll实例对象
|
||
downOption: {
|
||
auto: false // 不自动加载
|
||
},
|
||
upOption: {
|
||
auto: false, // 不自动加载
|
||
page: {
|
||
num: 0, // 当前页码,默认0,回调之前会加1,即callback(page)会从1开始
|
||
size: 10 // 每页数据的数量
|
||
},
|
||
noMoreSize: 2, //如果列表已无数据,可设置列表的总数量要大于半页才显示无更多数据;避免列表数据过少(比如只有一条数据),显示无更多数据会不好看; 默认5
|
||
empty: {
|
||
tip: '~ 空空如也 ~', // 提示
|
||
btnText: '去看看'
|
||
},
|
||
onScroll: true
|
||
},
|
||
scrollY: 0,
|
||
// 鸿蒙下直接初始化为 true,避免 v-if 阻塞子组件创建导致 onReady 先于 inner mounted
|
||
isInit: true,
|
||
// 鸿蒙下用来强制重建 slot DOM 的 key
|
||
listSlotKey: 0
|
||
};
|
||
},
|
||
props: {
|
||
top: [String, Number],
|
||
size: [String, Number],
|
||
fixed: {
|
||
// 是否通过fixed固定mescroll的高度, 默认true
|
||
type: Boolean,
|
||
default() {
|
||
return true;
|
||
}
|
||
},
|
||
background: String,
|
||
topbar: Boolean,
|
||
paddingBoth: {
|
||
type: [String, Number],
|
||
default() {
|
||
return 0;
|
||
}
|
||
}
|
||
},
|
||
created() {
|
||
if (this.size) this.upOption.page.size = this.size;
|
||
// 鸿蒙下 ArkUI 对 slot 内 Vue 响应式更新失效,数据加载后强制重建 slot DOM
|
||
// 通过把 listSlotKey 自增,使 :key 变化,触发整个 slot 子树销毁重建
|
||
const oldUpCallback = this.upCallback;
|
||
this.upCallback = function() {
|
||
const ret = oldUpCallback.apply(this, arguments);
|
||
// 数据回来后 200ms 自增 key,强制 slot DOM 重建
|
||
setTimeout(() => {
|
||
this.listSlotKey = (this.listSlotKey || 0) + 1;
|
||
}, 200);
|
||
return ret;
|
||
};
|
||
},
|
||
mounted() {
|
||
// 统一在 watcher 里触发首屏 resetUpScroll,这里不做任何事情
|
||
// (H5/微信下 mescroll 已在 mounted 前就绪;鸿蒙下 mounted 时机不可靠,所以都不在这里调)
|
||
},
|
||
watch: {
|
||
// 统一在 mescroll 实例就绪时触发首屏 resetUpScroll
|
||
// H5/微信下 inner 的 $emit('init') 同步触发,watcher 在 mounted 之前就 fire,正常加载
|
||
// 鸿蒙下 $emit 被延迟到 onReady 之后,watcher 在那时 fire,也能加载
|
||
mescroll: {
|
||
immediate: false,
|
||
handler(newVal) {
|
||
if (newVal && typeof newVal.resetUpScroll === 'function') {
|
||
// 避免重复触发
|
||
if (this._autoLoadTriggered) return;
|
||
this._autoLoadTriggered = true;
|
||
// 等下一个 tick,确保 outer 已挂载、meScroll 内部 setBodyHeight 等已执行
|
||
setTimeout(() => {
|
||
if (this.mescroll && typeof this.mescroll.resetUpScroll === 'function') {
|
||
this.mescroll.resetUpScroll();
|
||
this.listenRefresh();
|
||
}
|
||
}, 0);
|
||
}
|
||
}
|
||
}
|
||
},
|
||
methods: {
|
||
// mescroll组件初始化的回调,可获取到mescroll对象
|
||
mescrollInit(mescroll) {
|
||
this.mescroll = mescroll;
|
||
},
|
||
/*下拉刷新的回调 */
|
||
downCallback() {
|
||
// 这里加载你想下拉刷新的数据, 比如刷新轮播数据
|
||
// loadSwiper();
|
||
// 下拉刷新的回调,默认重置上拉加载列表为第一页 (自动执行 mescroll.num=1, 再触发upCallback方法 )
|
||
this.mescroll.resetUpScroll();
|
||
this.listenRefresh();
|
||
},
|
||
/*上拉加载的回调: mescroll携带page的参数, 其中num:当前页 从1开始, size:每页数据条数,默认10 */
|
||
upCallback() {
|
||
//联网加载数据
|
||
this.$emit('getData', this.mescroll);
|
||
},
|
||
//点击空布局按钮的回调
|
||
emptyClick() {
|
||
this.$emit('emptytap', this.mescroll);
|
||
},
|
||
//刷新
|
||
refresh() {
|
||
this.mescroll.resetUpScroll();
|
||
this.listenRefresh();
|
||
},
|
||
myScrollTo(y, t) {
|
||
this.mescroll.myScrollTo(y, t);
|
||
},
|
||
listenRefresh() {
|
||
this.$emit('listenRefresh', true);
|
||
},
|
||
/**
|
||
* 主动重建 slot DOM。
|
||
* 鸿蒙下通过 :key 变化重建的 .goods-item 元素 @click 事件绑定会丢失,
|
||
* 通过自增 listSlotKey 走 slot 重建路径可恢复事件绑定。
|
||
*/
|
||
forceSlotRebuild() {
|
||
this.listSlotKey = (this.listSlotKey || 0) + 1;
|
||
}
|
||
}
|
||
};
|
||
</script>
|