Files
lucky_shop/components/mescroll/my-list-mescroll.vue
ZF sun f258987e0e refactor: 替换多页面国际化文本为硬编码中文内容
移除项目内大部分$lang()国际化调用,替换为直接中文文本,统一前端展示文案
2026-06-23 08:55:16 +08:00

159 lines
4.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<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>