Skip to content

Commit f06e2b0

Browse files
author
yandadaFreedom
committed
feat: web&小程序支持sectionfooter
1 parent c3a64eb commit f06e2b0

5 files changed

Lines changed: 132 additions & 13 deletions

File tree

docs-vitepress/guide/extend/extend-component.md

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,24 +27,26 @@ Mpx 会根据当前编译的目标平台(wx/ali/web/ios/android/harmony),
2727
|-----------------------|-------------|----------|------------------------|-----------|
2828
| height | String/Number | 100% | 组件高度 | 微信小程序、支付宝小程序、Web、RN |
2929
| width | String/Number | 100% | 组件宽度 | 微信小程序、支付宝小程序、Web、RN |
30-
| listData | Array | [] | 列表数据,如需使用列表分组头 `section-header`,对应 item 的数据需要包含 `isSectionHeader: true` 标识 | 微信小程序、支付宝小程序、Web、RN |
30+
| listData | Array | [] | 列表数据,如需使用列表分组头 `section-header`,对应 item 的数据需要包含 `isSectionHeader: true` 标识;如需使用列表分组尾 `section-footer`,对应 item 的数据需要包含 `isSectionFooter: true` 标识 | 微信小程序、支付宝小程序、Web、RN |
3131
| enable-sticky | Boolean | false | 启用分组吸顶 | 微信小程序、支付宝小程序、Web、RN<br>⚠️微信小程序环境,需要使用 skyline 渲染模式,webview 模式不支持;web 环境仅支持移动端,不支持 pc 端 |
3232
| scroll-with-animation | Boolean | false | 滚动动画 | 微信小程序、支付宝小程序、Web、RN |
3333
| useListHeader | Boolean | false | 使用自定义列表头 | 微信小程序、支付宝小程序、Web、RN |
3434
| listHeaderData | Object | {} | 列表头数据 | 微信小程序、支付宝小程序、Web、RN |
3535
| useListFooter | Boolean | false | 使用自定义列表页脚 | 微信小程序、支付宝小程序、Web、RN |
36-
| listFooterData | Object | {} | 列表头数据 | 微信小程序、支付宝小程序、Web、RN |
36+
| listFooterData | Object | {} | 列表页脚数据 | 微信小程序、支付宝小程序、Web、RN |
3737
| generic:recycle-item | String | | 列表项,抽象节点组件名,对应组件需要通过 usingComponents 注册 | 微信小程序、支付宝小程序、Web、RN |
3838
| generic:section-header | String | | 列表分组头,抽象节点组件名,对应组件需要通过 usingComponents 注册 | 微信小程序、支付宝小程序、Web、RN |
39+
| generic:section-footer | String | | 列表分组尾,抽象节点组件名,对应组件需要通过 usingComponents 注册 | 微信小程序、支付宝小程序、Web、RN |
3940
| generic:list-header | String | | 列表头,抽象节点组件名,对应组件需要通过 usingComponents 注册 | 微信小程序、支付宝小程序、Web、RN |
4041
| generic:list-footer | String | | 列表页脚,抽象节点组件名,对应组件需要通过 usingComponents 注册 | 微信小程序、支付宝小程序、Web、RN |
4142
| itemHeight | Object | {} | 列表项高度配置(支持 getter/value),必须配置 | 微信小程序、支付宝小程序、Web、RN |
4243
| sectionHeaderHeight | Object | {} | 分组头部高度配置(getter/value),若使用了自定义分组头必须配置 | 微信小程序、支付宝小程序、Web、RN |
44+
| sectionFooterHeight | Object | {} | 分组尾部高度配置(getter/value),若使用了自定义分组尾必须配置 | 微信小程序、支付宝小程序、Web、RN |
4345
| listHeaderHeight | Object | {} | 列表头部高度配置(getter/value),若使用了列表头必须配置 | 微信小程序、支付宝小程序、Web、RN |
4446
| bufferScale | Number | 1 | 渲染缓冲区行数(虚拟滚动优化) | 仅支付宝小程序/web支持 |
4547
| minRenderCount | Number | 10 | 最小渲染项目数 | 仅支付宝小程序/web支持 |
4648

47-
#### `itemHeight`/`sectionHeaderHeight`/`listHeaderHeight` 格式说明
49+
#### `itemHeight`/`sectionHeaderHeight`/`sectionFooterHeight`/`listHeaderHeight` 格式说明
4850

4951
高度相关属性支持如下格式:
5052

@@ -86,12 +88,14 @@ height: {
8688
<section-list
8789
generic:recycle-item="normal-recycle-item"
8890
generic:section-header="section-header"
91+
generic:section-footer="section-footer"
8992
generic:list-header="list-header"
9093
width="{{width}}"
9194
height="{{height}}"
9295
listData="{{dataList}}"
9396
itemHeight="{{ itemHeight }}"
9497
sectionHeaderHeight="{{headerHeight}}"
98+
sectionFooterHeight="{{footerHeight}}"
9599
listHeaderHeight="{{listHeaderHeight}}"
96100
bufferScale="{{bufferScale}}"
97101
useListHeader="{{true}}"
@@ -118,6 +122,11 @@ height: {
118122
description: `This is item number ${itemNumber} in section ${i + 1}`
119123
})
120124
}
125+
126+
data.push({
127+
isSectionFooter: true, // 标识该行使用 section-footer 对应的抽象节点渲染
128+
title: `Section ${i + 1} Footer`
129+
})
121130
}
122131
return data
123132
}
@@ -138,6 +147,9 @@ height: {
138147
headerHeight: {
139148
value: 50
140149
},
150+
footerHeight: {
151+
value: 50
152+
},
141153
listHeaderHeight: {
142154
value: 100
143155
}
@@ -154,6 +166,7 @@ height: {
154166
"section-list": "@mpxjs/webpack-plugin/lib/runtime/components/extends/section-list",
155167
"normal-recycle-item": "@/components/recycle-item",
156168
"section-header": "@/components/section-header",
169+
"section-footer": "@/components/section-footer",
157170
"list-header": "@/components/list"
158171
}
159172
}
@@ -162,12 +175,13 @@ height: {
162175

163176
### 其它说明
164177

165-
- 当使用了列表项、列表头或者自定义分组头,必须配置对应 item/sectionHeader/listHeader 的 height 相关参数,否则会出现滚动异常情况。
178+
- 当使用了列表项、列表头、自定义分组头或者自定义分组尾,必须配置对应 item/sectionHeader/sectionFooter/listHeader 的 height 相关参数,否则会出现滚动异常情况。
166179
- 可直接调用 ref 实例执行 `scrollToIndex` 方法实现滚动。
167180
- 如果用户滑动的速度超过渲染的速度,则会先看到空白的内容,这是为了长列表优化不得不作出的妥协。
168181
- 当某行滑出渲染区域之外后,其内部状态将不会保留。
169182
- 在 RN 环境,section-list 通过 RN 提供的 SectionList 实现分组吸顶。受 RN 底层实现机制限制,开启 `enable-sticky` 且快速滑动时,自定义分组头有时会出现闪烁现象。此问题需要等待 RN 官方修复,我们会持续关注并跟进。
170-
- 若某行需要使用 `section-header` 对应的抽象节点渲染,则该行数据必须包含 `isSectionHeader: true` 字段;否则默认使用 `recycle-item` 对应的抽象节点渲染
183+
- 若某行需要使用 `section-header` 对应的抽象节点渲染,则该行数据必须包含 `isSectionHeader: true` 字段;若某行需要使用 `section-footer` 对应的抽象节点渲染,则该行数据必须包含 `isSectionFooter: true` 字段;否则默认使用 `recycle-item` 对应的抽象节点渲染
184+
- `isSectionFooter: true` 的数据建议放在对应分组的最后一行、下一个 `isSectionHeader: true` 数据之前,用于表示当前分组的尾部。
171185

172186

173187
## sticky-section
@@ -251,4 +265,3 @@ height: {
251265
}
252266
</script>
253267
```
254-

packages/webpack-plugin/lib/runtime/components/ali/mpx-section-list.mpx

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,13 @@
3232
wx:key="header{{item.itemData.item_key || item._index}}"
3333
itemData="{{item.itemData}}"
3434
/>
35+
<section-footer
36+
wx:if="{{item.itemData && item.itemData.isSectionFooter}}"
37+
wx:key="footer{{item.itemData.item_key || item._index}}"
38+
itemData="{{item.itemData}}"
39+
/>
3540
<recycle-item
36-
wx:if="{{item.itemData && !item.itemData.isSectionHeader}}"
41+
wx:if="{{item.itemData && !item.itemData.isSectionHeader && !item.itemData.isSectionFooter}}"
3742
wx:key="item{{item.itemData.item_key || item._index}}"
3843
itemData="{{item.itemData}}"
3944
/>
@@ -116,6 +121,12 @@
116121
return {}
117122
}
118123
},
124+
sectionFooterHeight: {
125+
type: Object,
126+
value: () => {
127+
return {}
128+
}
129+
},
119130
listHeaderData: {
120131
type: Object,
121132
value: () => {
@@ -290,6 +301,14 @@
290301
},
291302
deep: true
292303
},
304+
sectionFooterHeight: {
305+
handler() {
306+
this.initPositions()
307+
this.setPlaceholderStyle()
308+
this.setStartOffset()
309+
},
310+
deep: true
311+
},
293312
listHeaderHeight: {
294313
handler() {
295314
this.initPositions()
@@ -336,7 +355,11 @@
336355
const height = this.getItemHeight(
337356
item.itemData,
338357
index,
339-
item.itemData.isSectionHeader ? 'sectionHeaderHeight' : 'itemHeight'
358+
item.itemData.isSectionHeader
359+
? 'sectionHeaderHeight'
360+
: item.itemData.isSectionFooter
361+
? 'sectionFooterHeight'
362+
: 'itemHeight'
340363
)
341364
const position = {
342365
index,
@@ -555,6 +578,9 @@
555578
"section-header": {
556579
"default": "../wx/mpx-section-list-default/section-header.mpx"
557580
},
581+
"section-footer": {
582+
"default": "../wx/mpx-section-list-default/section-footer.mpx"
583+
},
558584
"list-header": {
559585
"default": "../wx/mpx-section-list-default/list-header.mpx"
560586
},
@@ -563,4 +589,4 @@
563589
}
564590
}
565591
}
566-
</script>
592+
</script>

packages/webpack-plugin/lib/runtime/components/web/mpx-section-list.vue

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,17 @@
2626
:key="'header' + (item.itemData.item_key || item._index)"
2727
:itemData="item.itemData"
2828
/>
29+
<section-footer
30+
v-if="item.itemData && item.itemData.isSectionFooter"
31+
:key="'footer' + (item.itemData.item_key || item._index)"
32+
:itemData="item.itemData"
33+
/>
2934
<recycle-item
30-
v-if="item.itemData && !item.itemData.isSectionHeader"
35+
v-if="
36+
item.itemData &&
37+
!item.itemData.isSectionHeader &&
38+
!item.itemData.isSectionFooter
39+
"
3140
:key="'item' + (item.itemData.item_key || item._index)"
3241
:itemData="item.itemData"
3342
/>
@@ -112,6 +121,12 @@ export default {
112121
return {}
113122
}
114123
},
124+
sectionFooterHeight: {
125+
type: Object,
126+
default: () => {
127+
return {}
128+
}
129+
},
115130
listHeaderData: {
116131
type: Object,
117132
default: () => {
@@ -156,7 +171,8 @@ export default {
156171
genericlistHeader: String,
157172
genericlistFooter: String,
158173
genericrecycleItem: String,
159-
genericsectionHeader: String
174+
genericsectionHeader: String,
175+
genericsectionFooter: String
160176
},
161177
data() {
162178
return {
@@ -287,6 +303,12 @@ export default {
287303
},
288304
deep: true
289305
},
306+
sectionFooterHeight: {
307+
handler() {
308+
this.handleHeightChange()
309+
},
310+
deep: true
311+
},
290312
listHeaderHeight: {
291313
handler() {
292314
this.handleHeightChange()
@@ -330,6 +352,7 @@ export default {
330352
"recycle-item": this.genericrecycleItem ,
331353
"list-header": this.genericlistHeader,
332354
"section-header": this.genericsectionHeader,
355+
"section-footer": this.genericsectionFooter,
333356
"list-footer": this.genericlistFooter
334357
}
335358
@@ -364,7 +387,11 @@ export default {
364387
const height = this.getItemHeight(
365388
item.itemData,
366389
index,
367-
item.itemData.isSectionHeader ? "sectionHeaderHeight" : "itemHeight"
390+
item.itemData.isSectionHeader
391+
? "sectionHeaderHeight"
392+
: item.itemData.isSectionFooter
393+
? "sectionFooterHeight"
394+
: "itemHeight"
368395
);
369396
const position = {
370397
index,
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<template>
2+
<view class="mpx-section-footer-default">
3+
<view class="mpx-default-content">section-footer-default</view>
4+
</view>
5+
</template>
6+
7+
<script>
8+
import { createComponent } from '@mpxjs/core'
9+
createComponent({})
10+
</script>
11+
12+
<style lang="stylus" scoped>
13+
.mpx-section-footer-default
14+
margin 4px 16px
15+
padding 16px
16+
background #fff
17+
border-radius 8px
18+
box-shadow 0 2px 4px rgba(0,0,0,0.1)
19+
20+
.mpx-default-content
21+
display flex
22+
flex-direction column
23+
font-size 14px
24+
color #666
25+
26+
</style>

packages/webpack-plugin/lib/runtime/components/wx/mpx-section-list.mpx

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@
2525
<!-- section items -->
2626
<recycle-item itemData="{{ subItem.itemData }}" id="{{ subItem._domId }}"></recycle-item>
2727
</block>
28+
<block wx:if="{{ item.hasSectionFooter }}">
29+
<section-footer itemData="{{ item.footerData }}" id="{{ item._footerDomId }}"></section-footer>
30+
</block>
2831
</sticky-section>
2932
</block>
3033
<block wx:if="{{ useListFooter }}">
@@ -156,18 +159,39 @@ createComponent({
156159
// 创建新的 section
157160
currentSection = {
158161
headerData: item,
162+
footerData: null,
159163
data: [],
160164
hasSectionHeader: true,
165+
hasSectionFooter: false,
161166
_domId: `mpx-recycle-item-${index}`
162167
}
168+
} else if (item.isSectionFooter) {
169+
// 如果没有当前 section,创建一个默认的
170+
if (!currentSection) {
171+
// 创建默认section (无header的section)
172+
currentSection = {
173+
headerData: null,
174+
footerData: null,
175+
data: [],
176+
hasSectionHeader: false,
177+
hasSectionFooter: false
178+
}
179+
}
180+
currentSection.footerData = item
181+
currentSection.hasSectionFooter = true
182+
currentSection._footerDomId = `mpx-recycle-item-${index}`
183+
sections.push(currentSection)
184+
currentSection = null
163185
} else {
164186
// 如果没有当前 section,创建一个默认的
165187
if (!currentSection) {
166188
// 创建默认section (无header的section)
167189
currentSection = {
168190
headerData: null,
191+
footerData: null,
169192
data: [],
170-
hasSectionHeader: false
193+
hasSectionHeader: false,
194+
hasSectionFooter: false
171195
}
172196
}
173197
currentSection.data.push({
@@ -198,6 +222,9 @@ createComponent({
198222
"section-header": {
199223
"default": "./mpx-section-list-default/section-header.mpx"
200224
},
225+
"section-footer": {
226+
"default": "./mpx-section-list-default/section-footer.mpx"
227+
},
201228
"list-header": {
202229
"default": "./mpx-section-list-default/list-header.mpx"
203230
},

0 commit comments

Comments
 (0)