Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
DCloud
hello uni-app x
提交
11c7816c
H
hello uni-app x
项目概览
DCloud
/
hello uni-app x
通知
6005
Star
91
Fork
164
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
18
列表
看板
标记
里程碑
合并请求
1
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
H
hello uni-app x
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
18
Issue
18
列表
看板
标记
里程碑
合并请求
1
合并请求
1
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
11c7816c
编写于
11月 18, 2024
作者:
雪洛
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat: uni-recycle-view适配微信小程序
上级
e71e5c8f
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
224 addition
and
42 deletion
+224
-42
pages/template/custom-long-list/custom-long-list.uvue
pages/template/custom-long-list/custom-long-list.uvue
+2
-1
uni_modules/uni-recycle-view/components/uni-recycle-item/uni-recycle-item.uvue
...le-view/components/uni-recycle-item/uni-recycle-item.uvue
+49
-35
uni_modules/uni-recycle-view/components/uni-recycle-view/uni-recycle-view.uvue
...le-view/components/uni-recycle-view/uni-recycle-view.uvue
+173
-6
未找到文件。
pages/template/custom-long-list/custom-long-list.uvue
浏览文件 @
11c7816c
...
@@ -5,7 +5,8 @@
...
@@ -5,7 +5,8 @@
此示例中仅渲染滚动容器上下5屏的内容。适用于仅使用一个for循环创建所有列表项的场景。文档详见插件市场:https://ext.dcloud.net.cn/plugin?id=17385</view>
此示例中仅渲染滚动容器上下5屏的内容。适用于仅使用一个for循环创建所有列表项的场景。文档详见插件市场:https://ext.dcloud.net.cn/plugin?id=17385</view>
<uni-recycle-view style="flex: 1;" :list="list" @scrolltoupper="scrolltoupper" @scroll="scroll">
<uni-recycle-view style="flex: 1;" :list="list" @scrolltoupper="scrolltoupper" @scroll="scroll">
<template v-slot:default="{items}">
<template v-slot:default="{items}">
<uni-recycle-item class="item" v-for="item in (items as Item[])" :item="item" :key="item.id">
<!-- scroll-view内:key只绑定数据内的id时在微信小程序端有Bug,表现为滚动位置跳动,初步判断为微信scroll-view的Bug。 -->
<uni-recycle-item class="item" v-for="(item, index) in (items as Item[])" :item="item" :key="index + '_' + item.id">
<view class="item-wrapper">
<view class="item-wrapper">
<view class="name"><text style="font-size: 14px;">{{item.name}}</text></view>
<view class="name"><text style="font-size: 14px;">{{item.name}}</text></view>
<view class="info"><text style="font-size: 12px; color: #999999;">{{item.info}}</text></view>
<view class="info"><text style="font-size: 12px; color: #999999;">{{item.info}}</text></view>
...
...
uni_modules/uni-recycle-view/components/uni-recycle-item/uni-recycle-item.uvue
浏览文件 @
11c7816c
<template>
<template>
<view class="item-container">
<view class="uni-recycle-view-item" :style="this.itemHeight != 0 ? {height: this.itemHeight + 'px'} : {}">
<slot></slot>
<slot></slot>
</view>
</view>
</template>
</template>
<script>
<script>
/**
/**
* recycle-item 长列表子项组件
* recycle-item 长列表子项组件
* @description 用于展示超长列表数据每一项
* @description 用于展示超长列表数据每一项
* @property {any[]} item 当前组件渲染的列表项
* @property {any[]} item 当前组件渲染的列表项
*/
*/
export default {
export default {
name: "uni-recycle-item",
name: "uni-recycle-item",
props: {
props: {
item: {
item: {
type: Object as PropType<any>,
type: Object as PropType<any>,
required: true
required: true
}
}
},
},
inject: {
inject: {
setCachedSize: {
itemHeight: {
type: Function as PropType<(item : any, size : number) => void>
type: Number as PropType<number>
},
},
},
setCachedSize: {
mounted() {
type: Function as PropType<(item : any, size : number) => void>
uni.createSelectorQuery().in(this).select('.item-container').boundingClientRect().exec((ret) => {
},
this.setCachedSize(this.item, (ret[0] as NodeInfo).height!)
getCachedSize: {
})
type: Function as PropType<(item : any) => number | null>
}
},
}
},
</script>
mounted() {
if (this.itemHeight == 0) {
<style>
const cachedSize = this.getCachedSize(this.item)
if(cachedSize == null) {
uni.createSelectorQuery().in(this).select('.uni-recycle-view-item').boundingClientRect().exec((ret) => {
this.setCachedSize(this.item, (ret[0] as NodeInfo).height!)
})
}
}
}
}
</script>
<style>
.uni-recycle-view-item {
box-sizing: border-box;
overflow: hidden;
}
</style>
</style>
uni_modules/uni-recycle-view/components/uni-recycle-view/uni-recycle-view.uvue
浏览文件 @
11c7816c
<template>
<template>
<scroll-view class="uni-recycle-view-main" v-bind="$attrs" ref="scroll" @scroll="onScroll">
<scroll-view class="uni-recycle-view-main"
<view :style="{ height: placeholderHeight + 'px' }">
ref="scroll"
<view :style="{ top: containerTop + 'px' }">
:type="type"
:direction="direction"
:associative-container="associativeContainer"
:enable-back-to-top="enableBackToTop"
:bounces="bounces"
:upper-threshold="upperThreshold"
:lower-threshold="lowerThreshold"
:scroll-top="scrollTop"
:scroll-left="scrollLeft"
:scroll-into-view="scrollIntoView"
:scroll-with-animation="scrollWithAnimation"
:refresher-enabled="refresherEnabled"
:refresher-threshold="refresherThreshold"
:refresher-max-drag-distance="refresherMaxDragDistance"
:refresher-default-style="refresherDefaultStyle"
:refresher-background="refresherBackground"
:refresher-triggered="refresherTriggered"
:show-scrollbar="showScrollbar"
:custom-nested-scroll="customNestedScroll"
:nested-scroll-child="nestedScrollChild"
@scroll="onScroll"
@scrollend="onScrollEnd"
@scrolltolower="onScrollToLower"
@scrolltoupper="onScrollToUpper"
@refresherabort="onRefresherAbort"
@refresherpulling="onRefresherPulling"
@refresherrefresh="onRefresherRefresh"
@refresherrestore="onRefresherRestore"
>
<view
:style="{ height: placeholderHeight + 'px' }"
class="uni-recycle-view-placeholder"
>
<view
:style="{ top: containerTop + 'px' }"
class="uni-recycle-view-container"
>
<slot :items="items"></slot>
<slot :items="items"></slot>
</view>
</view>
</view>
</view>
...
@@ -24,11 +60,104 @@
...
@@ -24,11 +60,104 @@
export default {
export default {
name: "uni-recycle-view",
name: "uni-recycle-view",
props: {
props: {
type: {
type: String,
default: ''
},
direction: {
type: String,
default: 'vertical'
},
associativeContainer: {
type: String,
default: ''
},
enableBackToTop: {
type: Boolean,
default: false
},
bounces: {
type: Boolean,
default: true
},
upperThreshold: {
type: Number,
default: 50
},
lowerThreshold: {
type: Number,
default: 50
},
scrollTop: {
type: Number,
default: 0
},
scrollLeft: {
type: Number,
default: 0
},
scrollIntoView: {
type: String,
default: ''
},
scrollWithAnimation: {
type: Boolean,
default: false
},
refresherEnabled: {
type: Boolean,
default: false
},
refresherThreshold: {
type: Number,
default: 45
},
refresherMaxDragDistance: {
type: Number
},
refresherDefaultStyle: {
type: String,
default: 'black'
},
refresherBackground: {
type: String,
default: 'transparent'
},
refresherTriggered: {
type: Boolean,
default: false
},
showScrollbar: {
type: Boolean,
default: true
},
customNestedScroll: {
type: Boolean,
default: false
},
nestedScrollChild: {
type: String,
default: ''
},
list: {
list: {
type: Array as PropType<any[]>,
type: Array as PropType<any[]>,
default: [] as any[]
default: [] as any[]
},
itemHeight: {
type: Number,
default: 0
}
}
},
},
emits: [
'scroll',
'scrollend',
'scrolltolower',
'scrolltoupper',
'refresherabort',
'refresherpulling',
'refresherrefresh',
'refresherrestore',
],
watch: {
watch: {
list: {
list: {
handler(list : any[]) {
handler(list : any[]) {
...
@@ -61,16 +190,26 @@
...
@@ -61,16 +190,26 @@
},
},
provide() {
provide() {
return {
return {
itemHeight: this.itemHeight,
setCachedSize: (item : any, size : number) => {
setCachedSize: (item : any, size : number) => {
if(this.itemHeight != 0) {
return
}
if (!this.hasDefaultSize) {
if (!this.hasDefaultSize) {
this.defaultItemSize = size
this.defaultItemSize = size
this.hasDefaultSize = true
this.hasDefaultSize = true
}
}
this.cachedSize.set(item, size)
this.cachedSize.set(item, size)
},
getCachedSize: (item : any) => {
return this.cachedSize.get(item)
}
}
}
}
},
},
created() {
created() {
if(this.itemHeight != 0) {
this.defaultItemSize = this.itemHeight!
}
this.placeholderHeight = this.list.length * this.defaultItemSize
this.placeholderHeight = this.list.length * this.defaultItemSize
},
},
mounted() {
mounted() {
...
@@ -83,7 +222,29 @@
...
@@ -83,7 +222,29 @@
})
})
},
},
methods: {
methods: {
onScrollEnd(e: UniScrollEvent) {
this.$emit('scrollend', e)
},
onScrollToLower(e: UniScrollToLowerEvent) {
this.$emit('scrolltolower', e)
},
onScrollToUpper(e: UniScrollToUpperEvent) {
this.$emit('scrolltoupper', e)
},
onRefresherAbort(e: UniRefresherEvent) {
this.$emit('refresherabort', e)
},
onRefresherPulling(e: UniRefresherEvent) {
this.$emit('refresherpulling', e)
},
onRefresherRefresh(e: UniRefresherEvent) {
this.$emit('refresherrefresh', e)
},
onRefresherRestore(e: UniRefresherEvent) {
this.$emit('refresherrestore', e)
},
onScroll(e : UniScrollEvent) {
onScroll(e : UniScrollEvent) {
this.$emit('scroll', e)
if (!this.initialized) {
if (!this.initialized) {
return
return
}
}
...
@@ -99,13 +260,12 @@
...
@@ -99,13 +260,12 @@
queue(scrollTop : number) {
queue(scrollTop : number) {
/*
/*
* rearrange内为大量同步逻辑,在上次rearrange未执行完毕的情况下将后续多个rearrange合并成一次执行,即仅执行最后一次
* rearrange内为大量同步逻辑,在上次rearrange未执行完毕的情况下将后续多个rearrange合并成一次执行,即仅执行最后一次
* 由于滚动机制差异,此优化仅在web端才有意义。
* 如何测试:push后console.log(this.rearrangeQueue.length) 输出结果大于1时触发优化
* 如何测试:push后console.log(this.rearrangeQueue.length) 输出结果大于1时触发优化
*/
*/
this.rearrangeQueue.push(scrollTop)
this.rearrangeQueue.push(scrollTop)
setTimeout(() => {
setTimeout(() => {
this.flush()
this.flush()
},
1
)
},
50
)
},
},
flush() {
flush() {
const queueLength = this.rearrangeQueue.length
const queueLength = this.rearrangeQueue.length
...
@@ -163,5 +323,12 @@
...
@@ -163,5 +323,12 @@
</script>
</script>
<style>
<style>
.uni-recycle-view-placeholder {
position: relative;
overflow: hidden;
}
.uni-recycle-view-container {
position: absolute;
width: 100%;
}
</style>
</style>
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录