yymini-pop-list 1.0.2 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,36 +1,106 @@
1
1
  # yymini-pop-list
2
- 小程序(抖音) 轻量级 底部列表弹出框 自定义组件,无需额外依赖,开箱即用。
2
+ 一款**轻量级、无额外依赖、开箱即用**的抖音/微信小程序底部列表弹出框自定义组件, 自定义列表数据源等核心功能,适用于底部列表选择、数据展示、参数配置等业务场景。
3
3
 
4
- ## 🌟 特性
5
- - 原生小程序语法,兼容小程序(抖音)基础库
6
- - 支持自定义标题、列表内容、背景图等
7
- - 提供 确认/取消 回调,支持遮罩关闭
8
- - 样式简洁美观,可自定义修改
9
-
10
- ## 📦 安装
11
- 在你的小程序项目根目录执行:
4
+ ## 特性
5
+ - 跨平台兼容:无缝适配**微信小程序**与**抖音小程序**,无需额外适配开发
6
+ - 列表交互完备:内置下拉刷新、上拉加载更多功能,支持分页控制与无更多数据状态管理
7
+ - 节点信息自治:弹窗显示时自动获取目标节点信息,无需外部手动调用
8
+ - 高度可定制:支持自定义节点选择器、弹窗高度、标题、按钮文本、背景图、返回按钮显示状态
9
+ - 灵活交互控制:支持遮罩点击关闭,弹窗主体点击防穿透
10
+ - 状态管理清晰:内置加载中、刷新中、无更多数据等状态,交互体验流畅
11
+ - 轻量无依赖:零外部依赖,引入即可使用,不增加项目体积负担
12
12
 
13
+ ## 安装
14
+ 1. 执行 npm 安装
13
15
  ```bash
14
16
  npm install yymini-pop-list --save
15
17
  or
16
18
  yarn add yymini-pop-list
17
-
18
- 然后在 开发者工具中 构建 NPM
19
19
  ```
20
+ 2. 小程序构建 npm
21
+ - 微信小程序:打开开发者工具 → 工具 → 构建 npm → 勾选「使用 npm 模块」
22
+ - 抖音小程序:打开开发者工具 → 工具 → 构建 npm
20
23
 
21
- ## 🎨 引用
24
+ ## 快速使用
25
+ ### 1. 配置组件
26
+ 在需要使用弹窗的页面或组件的 `json` 文件中声明组件引用:
22
27
  ```json
23
28
  {
24
29
  "usingComponents": {
25
30
  "pop-list": "/miniprogram_npm/yymini-pop-list/pop-list"
26
31
  }
27
32
  }
33
+ ```
28
34
 
35
+ ### 2. 页面中使用
36
+ 在 `ttml`、`wxml` 中添加组件标签,绑定属性与事件:
37
+ ```html
38
+ <!-- 页面 wxml -->
39
+
40
+ <pop-list
41
+ visible="{{isVisible}}"
42
+ title="参数列表"
43
+ selector=".btn-area"
44
+ isBackLeft="{{true}}"
45
+ btnText="关闭"
46
+ height="{{80}}"
47
+ bgSrc="/images/bg-list.png"
48
+ maskClosable="{{true}}"
49
+ dataList="{{dataList}}"
50
+ bind:close="onClose"
51
+ >
52
+ </pop-list>
29
53
  ```
30
- ## ▶️ use
31
- ```ttml / wxml
32
- <pop-list visible="{{true}}" title="这里是 title" dataList="[这里是列表数据]" bind:close="onClose" />
54
+
55
+ `js` 中控制弹窗显示与事件处理:
56
+ ```js
57
+ Page({
58
+ data: {
59
+ isVisible: false,
60
+ dataList: [
61
+ { key: 'width', value: '80rpx' },
62
+ { key: 'height', value: '60rpx' },
63
+ { key: 'top', value: '150rpx' }
64
+ ]
65
+ },
66
+ // 打开弹窗
67
+ openPopup() {
68
+ this.setData({ isVisible: true });
69
+ },
70
+ // 弹窗关闭事件(遮罩/关闭按钮触发)
71
+ onClose(e) {
72
+ console.log("弹窗关闭,触发类型:", e.detail.type);
73
+ this.setData({ isVisible: false });
74
+ }
75
+ })
33
76
  ```
34
77
 
35
- ## 👀 示例效果
36
- ![弹窗示例](https://raw.githubusercontent.com/AllenGe/yy/main/pop-image-list.png)
78
+ ## 组件属性
79
+ | 属性名 | 类型 | 默认值 | 说明 |
80
+ |----------------|---------|--------------|----------------------------------------------------------------------|
81
+ | visible | Boolean | false | 【必填】控制弹窗的显示/隐藏;显示时会自动触发getBtnAreaInfo获取节点信息 |
82
+ | zindex | Number | 999 | 弹窗及遮罩层层级,默认999,可根据页面元素层级调整,避免被遮挡 |
83
+ | selector | String | '.btn-area' | 节点选择器,指定需要获取信息的元素类名(需与页面元素类名一致) |
84
+ | isBackLeft | Boolean | true | 是否显示左侧返回按钮,默认显示 |
85
+ | title | String | null | 弹窗顶部标题,为null时不显示标题区域 |
86
+ | height | Number | 85 | 弹窗高度,单位为百分比(%),默认占屏幕高度的85% |
87
+ | btnText | String | '取消' | 关闭按钮文本,可自定义文案(如“关闭”“返回”等) |
88
+ | maskClosable | Boolean | true | 点击遮罩层是否关闭弹窗,默认关闭 |
89
+ | bgSrc | String | "bgSrc.png" | 弹窗背景图片地址,默认值为"bgSrc.png",需确保项目中存在该图片或自定义替换 |
90
+ | dataList | Array | [] | 列表数据源,格式为[{key: 'xxx', value: 'xxx'}, ...],用于初始化列表数据 |
91
+
92
+ ## 组件事件
93
+ | 事件名 | 触发时机 | 事件参数 | 说明 |
94
+ |----------------|--------------------------------------------|---------------------------|----------------------------------------------------------------------|
95
+ | bind:close | 点击遮罩层或关闭按钮时触发 | { type: String } | type取值:mask(遮罩)、close(关闭按钮),用于区分关闭来源 |
96
+
97
+ ## 效果预览
98
+ [效果预览地址](https://raw.githubusercontent.com/AllenGe/yy/main/pop-image-list.png)
99
+
100
+ ## 注意事项
101
+ 1. 平台适配:组件兼容微信小程序与抖音小程序,无需额外修改代码即可跨平台使用
102
+ 2. 数据源格式:dataList需传入数组格式,数组内每个元素需包含key和value字段,否则列表可能无法正常渲染
103
+ 3. 背景图配置:默认背景图地址为“bgSrc.png”,若项目中无该图片,需通过bgSrc属性自定义替换,否则可能显示空白背景
104
+ 4. 尺寸单位说明:height属性值为百分比,无需手动添加“%”符号,组件内部自动拼接处理;节点信息返回的尺寸单位为rpx
105
+ 5. 防穿透设计:弹窗主体区域点击不会穿透到遮罩层,已通过stopPropagation方法阻止事件冒泡
106
+ 6. 层级调整建议:若弹窗被其他页面元素遮挡,可增大zindex属性值(建议不超过9999,避免与系统层级冲突)
package/package.json CHANGED
@@ -1,13 +1,15 @@
1
1
  {
2
2
  "name": "yymini-pop-list",
3
- "version": "1.0.2",
4
- "description": "小程序(抖音)-底部列表弹出框 自定义组件",
3
+ "version": "1.0.4",
4
+ "description": "小程序(抖音、微信)-底部列表弹出框 自定义组件",
5
5
  "main": "pop-list.js",
6
6
  "miniprogram": ".",
7
7
  "keywords": [
8
8
  "douyin",
9
+ "weixin",
9
10
  "miniProgram",
10
11
  "抖音小程序",
12
+ "微信小程序",
11
13
  "confirm",
12
14
  "modal",
13
15
  "popup",
package/pop-list.ttml CHANGED
@@ -19,9 +19,9 @@
19
19
 
20
20
  <!-- 空页面 -->
21
21
  <view tt:elif="{{dataList.length < 1 }}" class="view-kong">
22
- <view style="flex: 0.4;width: 10%;"></view>
22
+ <view style="flex: 0.35;width: 10%;"></view>
23
23
  <image src="drow_kong2.png" class="drow_kong_box"></image>
24
- <view style="flex: 0.6;width: 10%;"></view>
24
+ <view style="flex: 0.65;width: 10%;"></view>
25
25
  </view>
26
26
 
27
27
  <!-- 数据加载完成后显示 -->
package/pop-list.ttss CHANGED
@@ -123,8 +123,8 @@ button::after {
123
123
  height: 120rpx;
124
124
  display: flex;
125
125
  flex: 1;
126
+ justify-content: center;
126
127
  align-items: center;
127
- /* justify-content: center; */
128
128
  /* background-color: #FFF; */
129
129
  }
130
130
 
@@ -132,8 +132,8 @@ button::after {
132
132
  flex: 1;
133
133
  display: flex;
134
134
  flex-direction: column;
135
- /* justify-content: center; */
136
135
  align-items: center;
136
+ /* justify-content: center; */
137
137
  }
138
138
 
139
139
  .drow_kong_box {
package/pop-list.wxml ADDED
@@ -0,0 +1,61 @@
1
+ <view class="view-mask {{visible ? 'show' : ''}}" style="z-index: {{zindex}};" bindtap="onMaskClick">
2
+ <view class="view-content" style="height: {{height}}%;" catchtap="stopPropagation">
3
+ <image src="{{bgSrc}}" class="img-bg"></image>
4
+ <view class="view-box">
5
+ <view class="view-top" bindtap="onClose">
6
+ <button wx:if="{{isBackLeft}}" class="btn-left" bindtap="onClose">
7
+ <image src="back.png" mode="widthFix"></image>
8
+ </button>
9
+ <view wx:else class="btn-left"></view>
10
+ <view class="toast-title">{{title}}</view>
11
+ <view class="btn-left"></view>
12
+ </view>
13
+
14
+ <!-- 加载中提示 -->
15
+ <view wx:if="{{loading}}" class="loading">
16
+ <view class="loading-circle"></view>
17
+ <text class="loading-text">加载中...</text>
18
+ </view>
19
+
20
+ <!-- 空页面 -->
21
+ <view wx:elif="{{dataList.length < 1 }}" class="view-kong">
22
+ <view style="flex: 0.35;width: 10%;"></view>
23
+ <image src="drow_kong2.png" class="drow_kong_box"></image>
24
+ <view style="flex: 0.65;width: 10%;"></view>
25
+ </view>
26
+
27
+ <!-- 数据加载完成后显示 -->
28
+ <view wx:else class="info-wrap">
29
+ <scroll-view scroll-y="true" class="info-scroll" refresher-enabled="true" enhanced="true" bounces="true"
30
+ refresher-background="#FFFFFF00" refresher-triggered="{{refreshing}}"
31
+ bindrefresherrefresh="onRefresherRefresh" bindscrolltolower="onScrollToLower">
32
+ <view class="param-item" wx:for="{{dataList}}" wx:key="key" wx:index="index">
33
+ <view class="param-key"
34
+ style="{{item.key=='height'?'background-color: #666;' : 'background-color: #999;'}}">
35
+ {{index}}- {{item.key}}
36
+ </view>
37
+ <view class="param-value">{{item.value}}</view>
38
+ </view>
39
+ <!-- <view class="pullup-loading" wx:if="{{loadingMore}}">
40
+ <view class="dot"></view>
41
+ <view class="dot"></view>
42
+ <view class="dot"></view>
43
+ </view> -->
44
+ <view wx:if="{{loadingMore}}" class="loading-more">
45
+ <view class="loading-circle"></view>
46
+ <text class="loading-text">正在加载...</text>
47
+ </view>
48
+ <view wx:elif="{{noMore}}" class="loading-no">
49
+ <view class="loading-line"></view>
50
+ <view class="loading-dot"></view>
51
+ <view class="loading-line"></view>
52
+ </view>
53
+ </scroll-view>
54
+ </view>
55
+
56
+ <view wx:if="{{!loading && btnText}}" class="cancel-button" bindtap="onClose">
57
+ {{btnText}}
58
+ </view>
59
+ </view>
60
+ </view>
61
+ </view>
package/pop-list.wxss ADDED
@@ -0,0 +1,341 @@
1
+ /* 重置 button 本身的边框和外轮廓 */
2
+ button {
3
+ border: none !important;
4
+ /* 去掉默认边框 */
5
+ outline: none !important;
6
+ /* 去掉点击外轮廓(可选) */
7
+ background: transparent;
8
+ /* 可选:去掉默认背景色 */
9
+ border-radius: 0;
10
+ /* 可选:去掉默认圆角 */
11
+ }
12
+
13
+ /* 关键:去掉 button 伪元素 ::after 的边框(抖音小程序默认通过这个渲染边框) */
14
+ button::after {
15
+ border: none !important;
16
+ }
17
+
18
+ /* 弹窗遮罩层 */
19
+ .view-mask {
20
+ position: fixed;
21
+ top: 0;
22
+ left: 0;
23
+ right: 0;
24
+ bottom: 0;
25
+ display: flex;
26
+ flex: 1;
27
+ flex-direction: column;
28
+ background: rgba(0, 0, 0, 0.45);
29
+
30
+ opacity: 0;
31
+ pointer-events: none;
32
+ transition: opacity 0.45s ease;
33
+ z-index: 9999;
34
+
35
+ }
36
+
37
+ .view-mask.show {
38
+ opacity: 1;
39
+ pointer-events: auto;
40
+ }
41
+
42
+
43
+ .img-bg {
44
+ width: 100%;
45
+ height: 100%;
46
+ }
47
+
48
+ /* 弹窗内容区 */
49
+ .view-content {
50
+ position: absolute;
51
+ bottom: 0;
52
+ left: 0;
53
+ right: 0;
54
+
55
+ border-top-left-radius: 40rpx;
56
+ border-top-right-radius: 40rpx;
57
+
58
+ display: flex;
59
+ flex-direction: column;
60
+ overflow: hidden;
61
+
62
+ /* background: #FFF; */
63
+ /* 初始状态:滑出屏幕底部 */
64
+ transform: translateY(100%);
65
+ transition: transform 0.45s ease-out;
66
+ /* 滑动动画更丝滑 */
67
+ /* height: 50%; */
68
+ max-height: 90%;
69
+ min-height: 50%;
70
+
71
+ }
72
+
73
+ .view-mask.show .view-content {
74
+ transform: translateY(0);
75
+ }
76
+
77
+ .view-box {
78
+ position: absolute;
79
+ left: 0;
80
+ top: 0;
81
+ right: 0;
82
+ bottom: 0;
83
+ display: flex;
84
+ flex-direction: column;
85
+ }
86
+
87
+ .view-top {
88
+ height: 120rpx;
89
+ display: flex;
90
+ flex-direction: row;
91
+ /* justify-content: center; */
92
+ align-items: center;
93
+ /* background-color: #00000080; */
94
+ }
95
+
96
+ .btn-left {
97
+ /* background-color: #FFF; */
98
+ /* background-color: #0088ff; */
99
+ display: flex;
100
+ height: 120rpx;
101
+ width: 96rpx;
102
+ justify-content: center;
103
+ align-items: center;
104
+ }
105
+
106
+ .btn-left:active {
107
+ box-shadow: inset 0 0 2rpx rgba(0, 0, 0, 0.05);
108
+ opacity: 0.9;
109
+ }
110
+
111
+ .img-left {
112
+ width: 48rpx;
113
+ height: 48rpx;
114
+ /* background-color: #000; */
115
+ }
116
+
117
+
118
+ /* 标题样式 */
119
+ .toast-title {
120
+ font-weight: bold;
121
+ font-size: 32rpx;
122
+ text-align: center;
123
+ height: 120rpx;
124
+ display: flex;
125
+ flex: 1;
126
+ justify-content: center;
127
+ align-items: center;
128
+ /* background-color: #FFF; */
129
+ }
130
+
131
+ .view-kong {
132
+ flex: 1;
133
+ display: flex;
134
+ flex-direction: column;
135
+ align-items: center;
136
+ /* justify-content: center; */
137
+ }
138
+
139
+ .drow_kong_box {
140
+ width: 400rpx;
141
+ height: 271rpx;
142
+ }
143
+
144
+ /* 取消按钮 */
145
+ .cancel-button {
146
+ height: 100rpx;
147
+ width: 100%;
148
+ display: flex;
149
+ justify-content: center;
150
+ align-items: center;
151
+ background: #FFF;
152
+ border-top: 1rpx solid #e8e8e8;
153
+ font-size: 32rpx;
154
+ color: #333;
155
+ padding-bottom: 30rpx;
156
+ }
157
+
158
+ /* 组件 showAllInfo.ttss - 新增/修改样式 */
159
+ .info-wrap {
160
+ display: flex;
161
+ flex: 1;
162
+ padding: 1rpx 40rpx;
163
+ overflow: hidden;
164
+ /* background-color: #f7f7f7; */
165
+
166
+ }
167
+
168
+ .info-scroll {
169
+ width: 100%;
170
+ /* height: 100%; */
171
+ /* background-color: #0088ff; */
172
+ flex: 1;
173
+ /* padding-bottom: 30rpx; */
174
+ }
175
+
176
+
177
+ /* 一行两个参数的容器:横向排列 */
178
+ .param-item {
179
+ display: flex;
180
+ width: 100%;
181
+ /* border-bottom: 20rpx solid #FFFFFF00; */
182
+ /* 可选:加分割线,更清晰 */
183
+ border-radius: 10rpx;
184
+ overflow: hidden;
185
+ margin-bottom: 20rpx;
186
+ }
187
+
188
+ /* 第一个参数(参数名)样式 */
189
+ .param-key {
190
+ flex: 1;
191
+ padding: 30rpx;
192
+ font-size: 26rpx;
193
+ color: #fff;
194
+ text-align: center;
195
+ }
196
+
197
+ /* 第二个参数(参数值)样式 */
198
+ .param-value {
199
+ flex: 1;
200
+ padding: 30rpx;
201
+ font-size: 26rpx;
202
+ color: #333;
203
+ text-align: center;
204
+ background-color: #ccc;
205
+ }
206
+
207
+
208
+ /* 3. 参数项强制颜色,避免和背景色一致 */
209
+ .params {
210
+ padding: 30rpx;
211
+ font-size: 26rpx;
212
+ color: #000 !important;
213
+ /* 强制黑色,避免白色看不见 */
214
+ /* background-color: #999; */
215
+ /* 临时加背景色 */
216
+ }
217
+
218
+
219
+ /* 加载中样式 */
220
+ .loading {
221
+ flex: 1;
222
+ display: flex;
223
+ justify-content: center;
224
+ /* align-items: center; */
225
+ padding-top: 25%;
226
+ font-size: 28rpx;
227
+ color: #666;
228
+ /* background-color: #f7f7f7; */
229
+ gap: 20rpx;
230
+ }
231
+
232
+ .loading-more {
233
+ display: flex;
234
+ height: 100rpx;
235
+ justify-content: center;
236
+ padding-top: 10rpx;
237
+ /* align-items: center; */
238
+ font-size: 24rpx;
239
+ color: #666;
240
+ /* background-color: red; */
241
+ gap: 20rpx;
242
+ }
243
+
244
+ .loading-no {
245
+ display: flex;
246
+ height: 100rpx;
247
+ justify-content: center;
248
+ padding-top: 10rpx;
249
+ /* align-items: center; */
250
+ gap: 20rpx;
251
+
252
+ }
253
+
254
+ .loading-line {
255
+ width: 60rpx;
256
+ height: 1rpx;
257
+ background-color: #999;
258
+ }
259
+
260
+ .loading-dot {
261
+ width: 10rpx;
262
+ height: 10rpx;
263
+ border-radius: 50%;
264
+ background-color: #999;
265
+ }
266
+
267
+ /* 转圈 loading 圆圈样式 */
268
+ .loading-circle {
269
+ width: 28rpx;
270
+ height: 28rpx;
271
+ border: 4rpx solid #e0e0e0;
272
+ /* 灰色边框(底色) */
273
+ border-top-color: #666;
274
+ /* 顶部蓝色(动效色) */
275
+ border-radius: 50%;
276
+ /* 圆形 */
277
+ animation: loading-rotate 1s linear infinite;
278
+ /* 旋转动画 */
279
+ }
280
+
281
+ /* 旋转动画关键帧 */
282
+ @keyframes loading-rotate {
283
+ 0% {
284
+ transform: rotate(0deg);
285
+ }
286
+
287
+ 100% {
288
+ transform: rotate(360deg);
289
+ }
290
+ }
291
+
292
+ /* Loading 文字样式(可选优化) */
293
+ .loading-text {
294
+ font-size: 24rpx;
295
+ color: #666;
296
+ letter-spacing: 2rpx;
297
+ }
298
+
299
+
300
+ /* 上拉加载3个点容器 */
301
+ .pullup-loading {
302
+ height: 80rpx;
303
+ display: flex;
304
+ justify-content: center;
305
+ align-items: center;
306
+ gap: 12rpx;
307
+ /* 点之间的间距 */
308
+ /* background-color: #f7f7f7; */
309
+ }
310
+
311
+ /* 单个点样式 */
312
+ .pullup-loading .dot {
313
+ width: 14rpx;
314
+ height: 14rpx;
315
+ border-radius: 50%;
316
+ background-color: #999;
317
+ animation: dot-flash 1.4s ease-in-out infinite both;
318
+ }
319
+
320
+ /* 3个点依次闪烁(和原生下拉动画一致) */
321
+ .pullup-loading .dot:nth-child(1) {
322
+ animation-delay: -0.32s;
323
+ }
324
+
325
+ .pullup-loading .dot:nth-child(2) {
326
+ animation-delay: -0.16s;
327
+ }
328
+
329
+ /* 闪烁动画关键帧 */
330
+ @keyframes dot-flash {
331
+
332
+ 0%,
333
+ 100%,
334
+ 80% {
335
+ opacity: 0.2;
336
+ }
337
+
338
+ 40% {
339
+ opacity: 1;
340
+ }
341
+ }