uview-pro 0.3.1 → 0.3.2
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/changelog.md
CHANGED
|
@@ -1,3 +1,22 @@
|
|
|
1
|
+
## 0.3.2(2025-10-15)
|
|
2
|
+
|
|
3
|
+
### 📝 Documentation | 文档
|
|
4
|
+
|
|
5
|
+
- **changelog:** 更新 CHANGELOG.md 生成配置 ([27a2609](https://github.com/anyup/uView-Pro/commit/27a26095b92cf8cbc6477c563a68b1557f9fb045))
|
|
6
|
+
- 更新交流群图片链接 ([832815d](https://github.com/anyup/uView-Pro/commit/832815deb63f8b144f525591d16e3ccf900b8632))
|
|
7
|
+
|
|
8
|
+
### ⚡ Performance Improvements | 性能优化
|
|
9
|
+
|
|
10
|
+
- **component-relation:** 增强组件间通信功能;修改 broadcast 方法,支持定向广播;移除对子组件名称的强制要求,允许匿名组件 ([28ea814](https://github.com/anyup/uView-Pro/commit/28ea814810055aa4c99b53d676b16da337fdf7d5))
|
|
11
|
+
|
|
12
|
+
### 🐛 Bug Fixes | Bug 修复
|
|
13
|
+
|
|
14
|
+
- **u-index-list:** 重构索引锚点组件,兼容多端,修复IndexList索引列表在微信小程序没有吸顶效果 ([ce6a7a3](https://github.com/anyup/uView-Pro/commit/ce6a7a3c01b622cad268779098390c0d593f75bc))
|
|
15
|
+
|
|
16
|
+
### 👥 Contributors
|
|
17
|
+
|
|
18
|
+
<a href="https://github.com/anyup"><img src="https://github.com/anyup.png?size=40" width="40" height="40" alt="anyup" title="anyup"/></a>
|
|
19
|
+
|
|
1
20
|
## 0.3.1(2025-10-14)
|
|
2
21
|
|
|
3
22
|
### 📝 Documentation | 文档
|
|
@@ -31,8 +31,8 @@ export default {
|
|
|
31
31
|
|
|
32
32
|
<script setup lang="ts">
|
|
33
33
|
import { IndexAnchorProps } from './types';
|
|
34
|
-
import { ref,
|
|
35
|
-
import { $u } from '../..';
|
|
34
|
+
import { ref, onMounted } from 'vue';
|
|
35
|
+
import { $u, useChildren } from '../..';
|
|
36
36
|
|
|
37
37
|
/**
|
|
38
38
|
* indexAnchor 索引列表锚点
|
|
@@ -46,28 +46,54 @@ import { $u } from '../..';
|
|
|
46
46
|
*/
|
|
47
47
|
|
|
48
48
|
const props = defineProps(IndexAnchorProps);
|
|
49
|
+
const { parentExposed } = useChildren('u-index-anchor', 'u-index-list');
|
|
49
50
|
|
|
50
51
|
// 响应式变量
|
|
51
52
|
const active = ref(false);
|
|
52
53
|
const wrapperStyle = ref<Record<string, any>>({});
|
|
53
54
|
const anchorStyle = ref<Record<string, any>>({});
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
const instance = getCurrentInstance();
|
|
55
|
+
const top = ref(0);
|
|
56
|
+
const height = ref(0);
|
|
57
57
|
|
|
58
58
|
// 挂载时查找父组件并注册
|
|
59
59
|
onMounted(() => {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
parent.exposed?.children.push(instance);
|
|
63
|
-
parent.exposed?.updateData();
|
|
60
|
+
if (parentExposed) {
|
|
61
|
+
parentExposed?.value?.updateData();
|
|
64
62
|
}
|
|
65
63
|
});
|
|
64
|
+
|
|
65
|
+
function setTop(val) {
|
|
66
|
+
top.value = val;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function setHeight(val) {
|
|
70
|
+
height.value = val;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function setActive(val) {
|
|
74
|
+
active.value = val;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function setAnchorStyle(val) {
|
|
78
|
+
anchorStyle.value = val;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function setWrapperStyle(val) {
|
|
82
|
+
wrapperStyle.value = val;
|
|
83
|
+
}
|
|
84
|
+
|
|
66
85
|
defineExpose({
|
|
86
|
+
props,
|
|
87
|
+
top,
|
|
88
|
+
height,
|
|
67
89
|
active,
|
|
68
90
|
wrapperStyle,
|
|
69
91
|
anchorStyle,
|
|
70
|
-
|
|
92
|
+
setTop,
|
|
93
|
+
setHeight,
|
|
94
|
+
setActive,
|
|
95
|
+
setAnchorStyle,
|
|
96
|
+
setWrapperStyle
|
|
71
97
|
});
|
|
72
98
|
</script>
|
|
73
99
|
|
|
@@ -49,7 +49,7 @@ export default {
|
|
|
49
49
|
|
|
50
50
|
<script setup lang="ts">
|
|
51
51
|
import { ref, reactive, computed, watch, onMounted, getCurrentInstance } from 'vue';
|
|
52
|
-
import { $u } from '../..';
|
|
52
|
+
import { $u, useParent } from '../..';
|
|
53
53
|
import { IndexListProps } from './types';
|
|
54
54
|
|
|
55
55
|
/**
|
|
@@ -84,8 +84,6 @@ const activeAnchorIndex = ref(0);
|
|
|
84
84
|
const showSidebar = ref(true);
|
|
85
85
|
const touchmove = ref(false);
|
|
86
86
|
const touchmoveIndex = ref(0);
|
|
87
|
-
// 孩子锚点组件
|
|
88
|
-
const children = reactive<any[]>([]);
|
|
89
87
|
const sidebar = reactive<{ height: number; top: number }>({ height: 0, top: 0 });
|
|
90
88
|
const scrollToAnchorIndex = ref<number | null>(null);
|
|
91
89
|
const timer = ref<any>(null);
|
|
@@ -101,8 +99,7 @@ const indexList = computed(() => props.indexList ?? getIndexList()).value;
|
|
|
101
99
|
const zIndex = computed(() => props.zIndex).value;
|
|
102
100
|
const activeColor = computed(() => props.activeColor).value;
|
|
103
101
|
|
|
104
|
-
|
|
105
|
-
children.length = 0;
|
|
102
|
+
const { children, broadcast } = useParent('u-index-anchor');
|
|
106
103
|
|
|
107
104
|
// 兼容 H5/非H5 stickyOffsetTop
|
|
108
105
|
onMounted(() => {
|
|
@@ -146,11 +143,9 @@ function setRect() {
|
|
|
146
143
|
function setAnchorsRect() {
|
|
147
144
|
return Promise.all(
|
|
148
145
|
children.map((anchor, index) => {
|
|
149
|
-
$u.getRect('.u-index-anchor-wrapper', anchor).then((rect: any) => {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
top: rect.top
|
|
153
|
-
});
|
|
146
|
+
$u.getRect('.u-index-anchor-wrapper', anchor.getInstance()).then((rect: any) => {
|
|
147
|
+
broadcast('setTop', rect.top, anchor.id);
|
|
148
|
+
broadcast('setHeight', rect.height, anchor.id);
|
|
154
149
|
});
|
|
155
150
|
})
|
|
156
151
|
);
|
|
@@ -182,9 +177,9 @@ function setSiderbarRect() {
|
|
|
182
177
|
function getActiveAnchorIndex() {
|
|
183
178
|
const sticky = props.sticky;
|
|
184
179
|
for (let i = children.length - 1; i >= 0; i--) {
|
|
185
|
-
const preAnchorHeight = i > 0 ? children[i - 1].height : 0;
|
|
180
|
+
const preAnchorHeight = i > 0 ? children[i - 1].getExposed().height.value : 0;
|
|
186
181
|
const reachTop = sticky ? preAnchorHeight : 0;
|
|
187
|
-
if (reachTop >= children[i].top) {
|
|
182
|
+
if (reachTop >= children[i].getExposed().top.value) {
|
|
188
183
|
return i;
|
|
189
184
|
}
|
|
190
185
|
}
|
|
@@ -203,7 +198,7 @@ function onScroll() {
|
|
|
203
198
|
if (sticky) {
|
|
204
199
|
let isActiveAnchorSticky = false;
|
|
205
200
|
if (active !== -1) {
|
|
206
|
-
isActiveAnchorSticky = children[active].top <= 0;
|
|
201
|
+
isActiveAnchorSticky = children[active].getExposed().top.value <= 0;
|
|
207
202
|
}
|
|
208
203
|
children.forEach((item, index) => {
|
|
209
204
|
if (index === active) {
|
|
@@ -212,7 +207,7 @@ function onScroll() {
|
|
|
212
207
|
color: `${activeColor}`
|
|
213
208
|
};
|
|
214
209
|
if (isActiveAnchorSticky) {
|
|
215
|
-
wrapperStyle = { height: `${children[index].height}px` };
|
|
210
|
+
wrapperStyle = { height: `${children[index].getExposed().height.value}px` };
|
|
216
211
|
anchorStyle = {
|
|
217
212
|
position: 'fixed',
|
|
218
213
|
top: `${stickyOffsetTop.value}px`,
|
|
@@ -220,31 +215,30 @@ function onScroll() {
|
|
|
220
215
|
color: `${activeColor}`
|
|
221
216
|
};
|
|
222
217
|
}
|
|
223
|
-
item.
|
|
224
|
-
item.
|
|
225
|
-
item.
|
|
218
|
+
broadcast('setActive', active, item.id);
|
|
219
|
+
broadcast('setAnchorStyle', anchorStyle, item.id);
|
|
220
|
+
broadcast('setWrapperStyle', wrapperStyle, item.id);
|
|
226
221
|
} else if (index === active - 1) {
|
|
227
222
|
const currentAnchor = children[index];
|
|
228
|
-
const currentOffsetTop = currentAnchor.top;
|
|
229
|
-
const targetOffsetTop =
|
|
223
|
+
const currentOffsetTop = currentAnchor.getExposed().top.value;
|
|
224
|
+
const targetOffsetTop =
|
|
225
|
+
index === children.length - 1 ? top.value : children[index + 1].getExposed().top.value;
|
|
230
226
|
const parentOffsetHeight = targetOffsetTop - currentOffsetTop;
|
|
231
|
-
const translateY = parentOffsetHeight - currentAnchor.height;
|
|
227
|
+
const translateY = parentOffsetHeight - currentAnchor.getExposed().height.value;
|
|
232
228
|
const anchorStyle = {
|
|
233
229
|
position: 'relative',
|
|
234
230
|
transform: `translate3d(0, ${translateY}px, 0)`,
|
|
235
231
|
zIndex: `${zIndex ? zIndex : $u.zIndex.indexListSticky}`,
|
|
236
232
|
color: `${activeColor}`
|
|
237
233
|
};
|
|
238
|
-
|
|
239
|
-
|
|
234
|
+
broadcast('setActive', active, currentAnchor.id);
|
|
235
|
+
broadcast('setAnchorStyle', anchorStyle, currentAnchor.id);
|
|
236
|
+
broadcast('setWrapperStyle', '', item.id);
|
|
240
237
|
} else {
|
|
241
|
-
item.
|
|
242
|
-
|
|
243
|
-
|
|
238
|
+
broadcast('setActive', false, item.id);
|
|
239
|
+
broadcast('setAnchorStyle', '', item.id);
|
|
240
|
+
broadcast('setWrapperStyle', '', item.id);
|
|
244
241
|
}
|
|
245
|
-
item.exposed.active = item.active;
|
|
246
|
-
item.exposed.anchorStyle = item.anchorStyle;
|
|
247
|
-
item.exposed.wrapperStyle = item.wrapperStyle;
|
|
248
242
|
});
|
|
249
243
|
}
|
|
250
244
|
}
|
|
@@ -284,12 +278,12 @@ function scrollToAnchor(index: number) {
|
|
|
284
278
|
return;
|
|
285
279
|
}
|
|
286
280
|
scrollToAnchorIndex.value = index;
|
|
287
|
-
const anchor = children.find(item => item.props.index === indexList[index]);
|
|
281
|
+
const anchor = children.find(item => item.getExposed().props.index === indexList[index]);
|
|
288
282
|
if (anchor) {
|
|
289
|
-
emit('select', anchor.props.index);
|
|
283
|
+
emit('select', anchor.getExposed().props.index);
|
|
290
284
|
uni.pageScrollTo({
|
|
291
285
|
duration: 0,
|
|
292
|
-
scrollTop: anchor.top + Number(props.scrollTop)
|
|
286
|
+
scrollTop: anchor.getExposed().top.value + Number(props.scrollTop)
|
|
293
287
|
});
|
|
294
288
|
}
|
|
295
289
|
}
|
|
@@ -7,7 +7,7 @@ interface ParentContext {
|
|
|
7
7
|
name: string;
|
|
8
8
|
addChild: (child: ChildContext) => void;
|
|
9
9
|
removeChild: (childId: string) => void;
|
|
10
|
-
broadcast: (event: string, data?: any) => void;
|
|
10
|
+
broadcast: (event: string, data?: any, childIds?: string | string[]) => void; // 修改:支持定向广播
|
|
11
11
|
getChildren: () => ChildContext[];
|
|
12
12
|
getExposed: () => Record<string, any>;
|
|
13
13
|
getChildExposed: (childId: string) => Record<string, any>;
|
|
@@ -80,6 +80,33 @@ export function useParent(componentName?: string) {
|
|
|
80
80
|
const children = reactive<ChildContext[]>([]);
|
|
81
81
|
const childrenMap = new Map<string, ChildContext>();
|
|
82
82
|
|
|
83
|
+
// 修改:增强broadcast方法,支持定向广播
|
|
84
|
+
const broadcast = (event: string, data?: any, childIds?: string | string[]) => {
|
|
85
|
+
let targetChildren: ChildContext[] = [];
|
|
86
|
+
|
|
87
|
+
if (childIds) {
|
|
88
|
+
// 处理单个childId或childId数组
|
|
89
|
+
const ids = Array.isArray(childIds) ? childIds : [childIds];
|
|
90
|
+
targetChildren = ids.map(id => childrenMap.get(id)).filter(Boolean) as ChildContext[];
|
|
91
|
+
} else {
|
|
92
|
+
// 没有指定childIds,广播给所有子组件
|
|
93
|
+
targetChildren = Array.from(childrenMap.values());
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
logger.log(`Parent ${name} broadcasting event: ${event} to ${targetChildren.length} children`);
|
|
97
|
+
|
|
98
|
+
targetChildren.forEach(child => {
|
|
99
|
+
const exposed = child.getExposed();
|
|
100
|
+
if (exposed && typeof exposed[event] === 'function') {
|
|
101
|
+
try {
|
|
102
|
+
exposed[event](data);
|
|
103
|
+
} catch (error) {
|
|
104
|
+
logger.warn(`Error calling child method ${event} for child ${child.id}:`, error);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
};
|
|
109
|
+
|
|
83
110
|
// 父组件上下文
|
|
84
111
|
const parentContext: ParentContext = {
|
|
85
112
|
name,
|
|
@@ -104,19 +131,7 @@ export function useParent(componentName?: string) {
|
|
|
104
131
|
}
|
|
105
132
|
},
|
|
106
133
|
|
|
107
|
-
broadcast
|
|
108
|
-
logger.log(`Parent ${name} broadcasting event: ${event} to ${childrenMap.size} children`);
|
|
109
|
-
childrenMap.forEach(child => {
|
|
110
|
-
const exposed = child.getExposed();
|
|
111
|
-
if (exposed && typeof exposed[event] === 'function') {
|
|
112
|
-
try {
|
|
113
|
-
exposed[event](data);
|
|
114
|
-
} catch (error) {
|
|
115
|
-
logger.warn(`Error calling child method ${event}:`, error);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
});
|
|
119
|
-
},
|
|
134
|
+
broadcast, // 使用新的broadcast方法
|
|
120
135
|
|
|
121
136
|
getChildren() {
|
|
122
137
|
return Array.from(childrenMap.values());
|
|
@@ -189,11 +204,12 @@ export function useChildren(componentName?: string, parentName?: string) {
|
|
|
189
204
|
|
|
190
205
|
// 使用组件名称作为默认名称
|
|
191
206
|
const name = componentName || instance.type.name || instance.type.__name;
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
207
|
+
// 修改:移除强制要求组件名称的报错,允许匿名组件
|
|
208
|
+
// if (!name) {
|
|
209
|
+
// throw new Error('Component name is required for useChildren. Either provide a name or set component name.');
|
|
210
|
+
// }
|
|
195
211
|
|
|
196
|
-
const instanceId = generateInstanceId(name);
|
|
212
|
+
const instanceId = generateInstanceId(name || 'anonymous');
|
|
197
213
|
const parentRef = ref<ParentContext | null>(null);
|
|
198
214
|
const parentExposed = ref<Record<string, any>>({});
|
|
199
215
|
|
|
@@ -238,9 +254,11 @@ export function useChildren(componentName?: string, parentName?: string) {
|
|
|
238
254
|
parentRef.value = parent;
|
|
239
255
|
parent.addChild(childContext);
|
|
240
256
|
getParentExposed();
|
|
241
|
-
logger.log(`Child ${name} linked to parent ${parent.name}`);
|
|
257
|
+
logger.log(`Child ${name || 'anonymous'} linked to parent ${parent.name}`);
|
|
242
258
|
return true;
|
|
243
259
|
}
|
|
260
|
+
// 修改:找不到父组件时不报错,只是记录日志
|
|
261
|
+
logger.log(`Child ${name || 'anonymous'} no parent found, working in standalone mode`);
|
|
244
262
|
return false;
|
|
245
263
|
};
|
|
246
264
|
|
|
@@ -258,14 +276,15 @@ export function useChildren(componentName?: string, parentName?: string) {
|
|
|
258
276
|
logger.warn(`Parent method ${event} not found or not a function`);
|
|
259
277
|
}
|
|
260
278
|
} else {
|
|
261
|
-
|
|
279
|
+
// 修改:父组件不存在时只记录调试日志,不报警告
|
|
280
|
+
logger.log(`No parent found to emit event: ${event}`);
|
|
262
281
|
}
|
|
263
282
|
};
|
|
264
283
|
|
|
265
284
|
// 子组件上下文
|
|
266
285
|
const childContext: ChildContext = {
|
|
267
286
|
id: instanceId,
|
|
268
|
-
name,
|
|
287
|
+
name: name || 'anonymous',
|
|
269
288
|
emitToParent,
|
|
270
289
|
getParentExposed,
|
|
271
290
|
getInstance() {
|
|
@@ -274,7 +293,7 @@ export function useChildren(componentName?: string, parentName?: string) {
|
|
|
274
293
|
getExposed
|
|
275
294
|
};
|
|
276
295
|
|
|
277
|
-
logger.log(`Child ${name} registered, looking for parent`);
|
|
296
|
+
logger.log(`Child ${name || 'anonymous'} registered, looking for parent`);
|
|
278
297
|
|
|
279
298
|
onMounted(() => {
|
|
280
299
|
// 立即尝试连接父组件
|
|
@@ -294,12 +313,12 @@ export function useChildren(componentName?: string, parentName?: string) {
|
|
|
294
313
|
if (parentRef.value) {
|
|
295
314
|
parentRef.value.removeChild(instanceId);
|
|
296
315
|
}
|
|
297
|
-
logger.log(`Child ${name} unmounted`);
|
|
316
|
+
logger.log(`Child ${name || 'anonymous'} unmounted`);
|
|
298
317
|
});
|
|
299
318
|
|
|
300
319
|
return {
|
|
301
320
|
childId: instanceId,
|
|
302
|
-
childName: name,
|
|
321
|
+
childName: name || 'anonymous',
|
|
303
322
|
parent: parentRef,
|
|
304
323
|
emitToParent,
|
|
305
324
|
getParentExposed,
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"id": "uview-pro",
|
|
3
3
|
"name": "uview-pro",
|
|
4
4
|
"displayName": "【Vue3重构版】uView Pro|基于Vue3+TS全面重构的70+精选UI组件库",
|
|
5
|
-
"version": "0.3.
|
|
5
|
+
"version": "0.3.2",
|
|
6
6
|
"description": "uView Pro,是全面支持Vue3的uni-app生态框架,70+精选组件已使用TypeScript重构,已全面支持uni-app Vue3.0",
|
|
7
7
|
"main": "index.ts",
|
|
8
8
|
"module": "index.ts",
|
package/readme.md
CHANGED
|
@@ -73,7 +73,7 @@ pnpm dev
|
|
|
73
73
|
|
|
74
74
|
<table class="table">
|
|
75
75
|
<tr>
|
|
76
|
-
<td><img src="https://ik.imagekit.io/anyup/images/social/weixin-chat.png
|
|
76
|
+
<td><img src="https://ik.imagekit.io/anyup/images/social/weixin-chat-cl.png" width="250" height="345" ></td>
|
|
77
77
|
<td><img src="https://ik.imagekit.io/anyup/images/social/qq-chat.png" width="250" height="345" ></td>
|
|
78
78
|
</tr>
|
|
79
79
|
<tr>
|