@cc-component/cc-ex-component 1.1.6 → 1.1.7
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/assets/core/BaseReference.ts +40 -0
- package/assets/{video/VideoComponent.ts.meta → core/BaseReference.ts.meta} +1 -1
- package/assets/core/BaseViewModelData.ts +12 -0
- package/assets/{video/Interface.ts.meta → core/BaseViewModelData.ts.meta} +1 -1
- package/assets/core/ReferenceComponent.ts +317 -0
- package/assets/core/ViewModel.ts +542 -0
- package/assets/{video/IVideo.ts.meta → core/ViewModel.ts.meta} +9 -9
- package/assets/ex/EXButton.ts +191 -0
- package/assets/ex/EXButton.ts.meta +9 -0
- package/assets/ex/ExCommon.ts +6 -4
- package/assets/ex/ExTool.ts +116 -0
- package/assets/ex/ExTool.ts.meta +9 -0
- package/assets/lib/collectView/lib-ext/custom-grid-flow-layout.ts +105 -0
- package/assets/lib/collectView/lib-ext/custom-grid-flow-layout.ts.meta +9 -0
- package/assets/lib/collectView/lib-ext/horizontal-center-layout.ts +84 -0
- package/assets/lib/collectView/lib-ext/horizontal-center-layout.ts.meta +9 -0
- package/assets/lib/collectView/lib-ext/yx-card-page-layout.ts +132 -0
- package/assets/lib/collectView/lib-ext/yx-card-page-layout.ts.meta +9 -0
- package/assets/lib/collectView/lib-ext/yx-carousel-layout.ts +156 -0
- package/assets/lib/collectView/lib-ext/yx-carousel-layout.ts.meta +9 -0
- package/assets/lib/collectView/lib-ext/yx-cover-layout.ts +405 -0
- package/assets/lib/collectView/lib-ext/yx-cover-layout.ts.meta +9 -0
- package/assets/lib/collectView/lib-ext/yx-masonry-flow-layout.ts +194 -0
- package/assets/lib/collectView/lib-ext/yx-masonry-flow-layout.ts.meta +9 -0
- package/assets/lib/collectView/lib-ext/yx-page-view.ts +232 -0
- package/assets/lib/collectView/lib-ext/yx-page-view.ts.meta +9 -0
- package/assets/lib/collectView/lib-ext/yx-table-view.ts +159 -0
- package/assets/lib/collectView/lib-ext/yx-table-view.ts.meta +9 -0
- package/assets/lib/collectView/lib-ext.meta +9 -0
- package/assets/lib/collectView/lib_collect/yx-collection-view.ts +1549 -0
- package/assets/lib/collectView/lib_collect/yx-collection-view.ts.meta +9 -0
- package/assets/lib/collectView/lib_collect/yx-compact-flow-layout.ts +364 -0
- package/assets/lib/collectView/lib_collect/yx-compact-flow-layout.ts.meta +9 -0
- package/assets/lib/collectView/lib_collect/yx-flow-layout.ts +909 -0
- package/assets/lib/collectView/lib_collect/yx-flow-layout.ts.meta +9 -0
- package/assets/lib/collectView/lib_collect/yx-table-layout.ts +352 -0
- package/assets/lib/collectView/lib_collect/yx-table-layout.ts.meta +9 -0
- package/assets/lib/collectView/lib_collect.meta +9 -0
- package/assets/{video/list.meta → lib/collectView.meta} +9 -9
- package/assets/lib/tableView/IListView.ts +17 -0
- package/assets/lib/tableView/IListView.ts.meta +9 -0
- package/assets/lib/tableView/ListView.ts +197 -0
- package/assets/lib/tableView/ListView.ts.meta +9 -0
- package/assets/lib/tableView/ListViewPage.ts +1048 -0
- package/assets/lib/tableView/ListViewPage.ts.meta +9 -0
- package/assets/lib/tableView/ListViewPageLoop.ts +922 -0
- package/assets/lib/tableView/ListViewPageLoop.ts.meta +1 -0
- package/assets/lib/tableView/TableView.ts +82 -0
- package/assets/lib/tableView/TableView.ts.meta +9 -0
- package/assets/lib/tableView.meta +9 -0
- package/assets/{video.meta → lib.meta} +1 -1
- package/assets/platform/Interface.ts +15 -10
- package/assets/platform/android/AndroidModule.ts +12 -0
- package/assets/platform/android/AndroidModule.ts.meta +9 -0
- package/assets/platform/android/AndroidSDK.ts +1 -2
- package/assets/platform/base/PlatfprmModule.ts +44 -29
- package/assets/platform/base/SDKBase.ts +2 -2
- package/assets/platform/base/TTSDK.ts +21 -10
- package/assets/platform/base/WXSDK.ts +15 -16
- package/assets/platform/wx/MiniSDK.ts +41 -3
- package/assets/platform/wx/wxmini.d.ts +2 -2
- package/index.ts +0 -1
- package/package.json +1 -1
- package/assets/core/ReferenceCollector.ts +0 -172
- package/assets/video/IVideo.ts +0 -73
- package/assets/video/Interface.ts +0 -25
- package/assets/video/VideoComponent.prefab +0 -614
- package/assets/video/VideoComponent.prefab.meta +0 -13
- package/assets/video/VideoComponent.ts +0 -33
- package/assets/video/VideoManager.ts +0 -399
- package/assets/video/VideoManager.ts.meta +0 -9
- package/assets/video/VideoModule.ts +0 -137
- package/assets/video/VideoModule.ts.meta +0 -9
- package/assets/video/VideoPlayTT.ts +0 -338
- package/assets/video/VideoPlayTT.ts.meta +0 -9
- package/assets/video/VideoPlayWX.ts +0 -274
- package/assets/video/VideoPlayWX.ts.meta +0 -9
- package/assets/video/VideoPlayWeb.ts +0 -228
- package/assets/video/VideoPlayWeb.ts.meta +0 -9
- /package/assets/core/{ReferenceCollector.ts.meta → ReferenceComponent.ts.meta} +0 -0
|
@@ -0,0 +1,542 @@
|
|
|
1
|
+
// assets/cc-ex-component/core/DataBinding.ts
|
|
2
|
+
import { Label } from 'cc';
|
|
3
|
+
import { sp } from 'cc';
|
|
4
|
+
import { Sprite } from 'cc';
|
|
5
|
+
import { ToggleContainer } from 'cc';
|
|
6
|
+
import { Size } from 'cc';
|
|
7
|
+
import { EventHandler } from 'cc';
|
|
8
|
+
import { EditBox, Toggle, Slider, Button, ProgressBar, Node } from 'cc';
|
|
9
|
+
import { RichText } from 'cc';
|
|
10
|
+
import { Component } from 'cc';
|
|
11
|
+
import { js } from 'cc';
|
|
12
|
+
import { escape } from 'querystring';
|
|
13
|
+
import { IIndexPath } from '../lib/tableView/IListView';
|
|
14
|
+
import { ListView } from '../lib/tableView/ListView';
|
|
15
|
+
import { TableView } from '../lib/tableView/TableView';
|
|
16
|
+
import { YXFlowLayout } from '../lib/collectView/lib_collect/yx-flow-layout';
|
|
17
|
+
import { math } from 'cc';
|
|
18
|
+
import { YXCollectionView, YXIndexPath } from '../lib/collectView/lib_collect/yx-collection-view';
|
|
19
|
+
|
|
20
|
+
interface IBindingData extends ITableViewEvents, IBindingDataEvents {
|
|
21
|
+
dataPath: string;
|
|
22
|
+
type: any;
|
|
23
|
+
// 允许任意额外属性
|
|
24
|
+
[key: string]: any;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
interface IBindingDataEvents {
|
|
29
|
+
reset?: Function;
|
|
30
|
+
event?: Function;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
interface ITableViewEvents {
|
|
35
|
+
/**列表相关 */
|
|
36
|
+
itemSize: (self: any) => Size,
|
|
37
|
+
cellForItemAt: (self: any, indexPath: IIndexPath, collectionView: ListView) => Node,
|
|
38
|
+
onTouchCellAt?: (self: any, indexPath: IIndexPath) => void
|
|
39
|
+
numberOfItems?: (self: any) => number;
|
|
40
|
+
moveFinish?: (self: any, indexPath: IIndexPath) => void
|
|
41
|
+
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
interface ICollectViewEvents {
|
|
45
|
+
/**列表相关 */
|
|
46
|
+
layout: (self: any) => YXFlowLayout,
|
|
47
|
+
cellForItemAt: (self: any, indexPath: YXIndexPath, collectionView: YXCollectionView) => Node
|
|
48
|
+
itemSize?: ((self: any, indexPath: YXIndexPath, layout: YXFlowLayout, collectionView: YXCollectionView) => math.Size),
|
|
49
|
+
onTouchCellAt?: (self: any, indexPath: YXIndexPath) => void
|
|
50
|
+
numberOfItems?: ((self: any, section: number, collectionView: YXCollectionView) => number);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// 全局存储绑定关系: { className -> { uiProp: dataPath } }
|
|
54
|
+
const bindingMap = new Map<string, Map<string, IBindingData>>();
|
|
55
|
+
const baseData = 'viewModel'
|
|
56
|
+
const skip = "$"
|
|
57
|
+
// const comType = {
|
|
58
|
+
// "cc.Sprite": typeof Sprite,
|
|
59
|
+
// "cc.Label": Label,
|
|
60
|
+
// "cc.RichText": RichText,
|
|
61
|
+
// "cc.Skeleton": sp.Skeleton,
|
|
62
|
+
|
|
63
|
+
// "cc.EditBox": EditBox,
|
|
64
|
+
// "cc.ProgressBar": ProgressBar,
|
|
65
|
+
|
|
66
|
+
// "cc.Slider": Slider,
|
|
67
|
+
// "cc.Toggle": Toggle,
|
|
68
|
+
// "cc.Button": Button,
|
|
69
|
+
// }
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* 数据绑定装饰器
|
|
73
|
+
* @param dataPath 数据路径(如 "data.name")
|
|
74
|
+
* @param reset 重写赋值方法,自定义实现. 参数:(self 组件所在的父类,com 组件,value 值)
|
|
75
|
+
* @param event 点击事件,滑动事件,等等. 参数:(self 组件所在的父类)
|
|
76
|
+
*/
|
|
77
|
+
export function Bind<T extends Component>(dataPath: string, param?: IBindingDataEvents) {
|
|
78
|
+
dataPath = baseData + '.' + dataPath;
|
|
79
|
+
return function (target: any, propertyKey: string) {
|
|
80
|
+
const className = js.getClassName(target.constructor);
|
|
81
|
+
if (!bindingMap.has(className)) {
|
|
82
|
+
bindingMap.set(className, new Map());
|
|
83
|
+
}
|
|
84
|
+
const data: IBindingData = {
|
|
85
|
+
dataPath: dataPath, type: null, reset: param?.reset, event: param?.event,
|
|
86
|
+
itemSize: null,
|
|
87
|
+
cellForItemAt: null,
|
|
88
|
+
numberOfItems: function (): number {
|
|
89
|
+
throw new Error('Function not implemented.');
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
bindingMap.get(className)!.set(propertyKey, data);
|
|
94
|
+
// 重写 onLoad 以初始化绑定
|
|
95
|
+
const originalOnLoad = target.constructor.prototype.onLoad;
|
|
96
|
+
target.constructor.prototype.onLoad = function () {
|
|
97
|
+
originalOnLoad?.call(this);
|
|
98
|
+
const com = this[propertyKey];
|
|
99
|
+
const classname = js.getClassName(com)
|
|
100
|
+
data.type = classname;
|
|
101
|
+
bindingMap.get(className)!.set(propertyKey, data);
|
|
102
|
+
// 初始化 UI
|
|
103
|
+
const value = this._getNestedValue(this, dataPath);
|
|
104
|
+
if (com) {
|
|
105
|
+
updateStatus(data, com, value, this)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// 记录绑定关系到实例
|
|
109
|
+
if (!this._bindings) this._bindings = [];
|
|
110
|
+
this._bindings.push({ uiProp: propertyKey, dataPath });
|
|
111
|
+
};
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export function BindTable<T extends Component>(dataPath: string, param?: ITableViewEvents) {
|
|
116
|
+
dataPath = baseData + '.' + dataPath;
|
|
117
|
+
return function (target: any, propertyKey: string) {
|
|
118
|
+
const className = js.getClassName(target.constructor);
|
|
119
|
+
if (!bindingMap.has(className)) {
|
|
120
|
+
bindingMap.set(className, new Map());
|
|
121
|
+
}
|
|
122
|
+
const data: IBindingData = {
|
|
123
|
+
dataPath: dataPath, type: null,
|
|
124
|
+
itemSize: param.itemSize,
|
|
125
|
+
cellForItemAt: param.cellForItemAt,
|
|
126
|
+
numberOfItems: param.numberOfItems,
|
|
127
|
+
onTouchCellAt: param.onTouchCellAt,
|
|
128
|
+
moveFinish: param.moveFinish,
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
bindingMap.get(className)!.set(propertyKey, data);
|
|
132
|
+
// 重写 onLoad 以初始化绑定
|
|
133
|
+
const originalOnLoad = target.constructor.prototype.onLoad;
|
|
134
|
+
target.constructor.prototype.onLoad = function () {
|
|
135
|
+
originalOnLoad?.call(this);
|
|
136
|
+
const com = this[propertyKey];
|
|
137
|
+
const classname = js.getClassName(com)
|
|
138
|
+
data.type = classname;
|
|
139
|
+
bindingMap.get(className)!.set(propertyKey, data);
|
|
140
|
+
// 初始化 UI
|
|
141
|
+
const value = this._getNestedValue(this, dataPath);
|
|
142
|
+
if (com) {
|
|
143
|
+
updateStatus(data, com, value, this)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// 记录绑定关系到实例
|
|
147
|
+
if (!this._bindings) this._bindings = [];
|
|
148
|
+
this._bindings.push({ uiProp: propertyKey, dataPath });
|
|
149
|
+
};
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export function BindCollect<T extends Component>(dataPath: string, param?: ICollectViewEvents) {
|
|
154
|
+
dataPath = baseData + '.' + dataPath;
|
|
155
|
+
return function (target: any, propertyKey: string) {
|
|
156
|
+
const className = js.getClassName(target.constructor);
|
|
157
|
+
if (!bindingMap.has(className)) {
|
|
158
|
+
bindingMap.set(className, new Map());
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const data: IBindingData = {
|
|
162
|
+
dataPath: dataPath, type: null,
|
|
163
|
+
layout: param.layout,
|
|
164
|
+
cellForItemAt: param.cellForItemAt as any,
|
|
165
|
+
numberOfItems: param.numberOfItems as any,
|
|
166
|
+
itemSize: param.itemSize as any,
|
|
167
|
+
onTouchCellAt: param.onTouchCellAt,
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// layout: (self: any) => YXFlowLayout,
|
|
171
|
+
// cellForItemAt: (self: any, indexPath: YXIndexPath, collectionView: YXCollectionView) => Node
|
|
172
|
+
// itemSize?: ((self: any, indexPath: YXIndexPath, layout: YXFlowLayout, collectionView: YXCollectionView) => math.Size),
|
|
173
|
+
// onTouchCellAt?: (self: any, indexPath: YXIndexPath) => void
|
|
174
|
+
// numberOfItems?: ((self: any, section: number, collectionView: YXCollectionView) => number);
|
|
175
|
+
bindingMap.get(className)!.set(propertyKey, data);
|
|
176
|
+
// 重写 onLoad 以初始化绑定
|
|
177
|
+
const originalOnLoad = target.constructor.prototype.onLoad;
|
|
178
|
+
target.constructor.prototype.onLoad = function () {
|
|
179
|
+
originalOnLoad?.call(this);
|
|
180
|
+
const com = this[propertyKey];
|
|
181
|
+
const classname = js.getClassName(com)
|
|
182
|
+
data.type = classname;
|
|
183
|
+
bindingMap.get(className)!.set(propertyKey, data);
|
|
184
|
+
// 初始化 UI
|
|
185
|
+
const value = this._getNestedValue(this, dataPath);
|
|
186
|
+
if (com) {
|
|
187
|
+
updateStatus(data, com, value, this)
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// 记录绑定关系到实例
|
|
191
|
+
if (!this._bindings) this._bindings = [];
|
|
192
|
+
this._bindings.push({ uiProp: propertyKey, dataPath });
|
|
193
|
+
};
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* 响应式绑定 Mixin(混入方法)
|
|
198
|
+
*/
|
|
199
|
+
export function ViewModel<T extends new (...args: any[]) => Component>(Base: T) {
|
|
200
|
+
return class extends Base {
|
|
201
|
+
// 绑定关系存储
|
|
202
|
+
_bindings: { uiProp: string; dataPath: string }[] = [];
|
|
203
|
+
viewModel: any
|
|
204
|
+
|
|
205
|
+
// 创建响应式数据
|
|
206
|
+
_makeReactive<T extends object>(obj: T, pathPrefix: string): T {
|
|
207
|
+
const self = this as any;
|
|
208
|
+
return new Proxy(obj, {
|
|
209
|
+
get(target, key: string) {
|
|
210
|
+
// ✅ 跳过 $ 开头的属性:直接返回原始值,不代理
|
|
211
|
+
if (key.startsWith(skip)) {
|
|
212
|
+
return target[key];
|
|
213
|
+
}
|
|
214
|
+
const value = target[key];
|
|
215
|
+
//暂时不循环找对象
|
|
216
|
+
// if (value !== null && typeof value === 'object' && !Array.isArray(value)) {
|
|
217
|
+
// console.log(`get ${pathPrefix}----${key}`);
|
|
218
|
+
// return self._makeReactive(value, `${pathPrefix}.${key}`);
|
|
219
|
+
// }
|
|
220
|
+
return value;
|
|
221
|
+
},
|
|
222
|
+
set(target, key: string, value: any) {
|
|
223
|
+
|
|
224
|
+
// ✅ 跳过 $ 开头的属性:不触发响应式更新
|
|
225
|
+
if (key.startsWith(skip)) {
|
|
226
|
+
target[key] = value;
|
|
227
|
+
return true;
|
|
228
|
+
}
|
|
229
|
+
else if (value?.skip) {
|
|
230
|
+
target[key] = value.value;
|
|
231
|
+
return true;
|
|
232
|
+
}
|
|
233
|
+
const fullPath = `${pathPrefix}.${key}`;
|
|
234
|
+
target[key] = value;
|
|
235
|
+
self._onDataChange?.(fullPath, value);
|
|
236
|
+
return true;
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// 获取嵌套值
|
|
242
|
+
_getNestedValue(obj: any, path: string) {
|
|
243
|
+
return path.split('.').reduce((current, key) => current?.[key], obj);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// 数据变化回调(可被子类 override)
|
|
247
|
+
_onDataChange(fullPath: string, newValue: any) {
|
|
248
|
+
if (!this._bindings) return;
|
|
249
|
+
this._bindings.forEach(({ uiProp, dataPath }) => {
|
|
250
|
+
if (fullPath === dataPath) {
|
|
251
|
+
const com = this[uiProp]
|
|
252
|
+
if (com) {
|
|
253
|
+
const classname = js.getClassName(this)
|
|
254
|
+
const data = bindingMap.get(classname).get(uiProp)
|
|
255
|
+
const value = this._getNestedValue(this, data.dataPath);
|
|
256
|
+
updateStatus(data, com, value, this)
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/** 解除当前组件的所有数据绑定 */
|
|
263
|
+
public unbindViewModel(): void {
|
|
264
|
+
// 1. 清空绑定关系(停止 _onDataChange 触发 UI 更新)
|
|
265
|
+
this._bindings = [];
|
|
266
|
+
// 2. 替换 data 为普通对象(破坏 Proxy 响应式)
|
|
267
|
+
this.viewModel = null
|
|
268
|
+
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// 在 withDataBinding 返回的 class 中
|
|
272
|
+
protected onDestroy(): void {
|
|
273
|
+
this.unbindViewModel();
|
|
274
|
+
super.onDestroy?.();
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
function updateStatus(data: IBindingData, com: Component, value: any, self: any) {
|
|
282
|
+
|
|
283
|
+
const sx = data.dataPath.split('.').pop();
|
|
284
|
+
const tempData = { value: value, skip: false }
|
|
285
|
+
switch (data.type) {
|
|
286
|
+
case 'cc.Label':
|
|
287
|
+
if (data.reset) {
|
|
288
|
+
data.reset(self, value, com);
|
|
289
|
+
} else {
|
|
290
|
+
if (value) (com as Label).string = value?.toString() || '';
|
|
291
|
+
}
|
|
292
|
+
break;
|
|
293
|
+
case 'cc.RichText':
|
|
294
|
+
if (data.reset) {
|
|
295
|
+
data.reset(self, value, com);
|
|
296
|
+
} else
|
|
297
|
+
if (value)
|
|
298
|
+
(com as RichText).string = value?.toString() || '';
|
|
299
|
+
break;
|
|
300
|
+
case 'cc.Sprite':
|
|
301
|
+
// 假设 value 是 SpriteFrame 路径或资源
|
|
302
|
+
// 需要额外处理资源加载逻辑
|
|
303
|
+
if (data.reset) {
|
|
304
|
+
data.reset(self, value, com);
|
|
305
|
+
} else
|
|
306
|
+
if (value) (com as Sprite).spriteFrame = value;
|
|
307
|
+
break;
|
|
308
|
+
case 'cc.Button':
|
|
309
|
+
const com_btn = (com as Button);
|
|
310
|
+
if (data.reset) {
|
|
311
|
+
data.reset(self, value, com);
|
|
312
|
+
} else
|
|
313
|
+
com_btn.node.active = value ?? true;
|
|
314
|
+
|
|
315
|
+
//事件
|
|
316
|
+
com_btn.node.off(Button.EventType.CLICK, com_btn['btnCall'], self);
|
|
317
|
+
tempData.skip = true;
|
|
318
|
+
const btnCall = (btn) => {
|
|
319
|
+
tempData.value = btn.node.active
|
|
320
|
+
self.viewModel[sx] = tempData
|
|
321
|
+
data.event?.(self)
|
|
322
|
+
}
|
|
323
|
+
com_btn['btnCall'] = btnCall
|
|
324
|
+
com_btn.node.on(Button.EventType.CLICK, com_btn['btnCall'], self);
|
|
325
|
+
break;
|
|
326
|
+
case 'cc.ProgressBar':
|
|
327
|
+
if (data.reset) {
|
|
328
|
+
data.reset(self, value, com);
|
|
329
|
+
} else
|
|
330
|
+
if (value) (com as ProgressBar).progress = Number(value) || 0;
|
|
331
|
+
break;
|
|
332
|
+
case 'cc.Skeleton':
|
|
333
|
+
if (data.reset) {
|
|
334
|
+
data.reset(self, value, com);
|
|
335
|
+
} else
|
|
336
|
+
if (value) (com as sp.Skeleton).skeletonData = value
|
|
337
|
+
break;
|
|
338
|
+
case 'cc.Slider':
|
|
339
|
+
const com_sld = (com as Slider);
|
|
340
|
+
if (data.reset) {
|
|
341
|
+
data.reset(self, value, com);
|
|
342
|
+
} else
|
|
343
|
+
if (value) com_sld.progress = Number(value) || 0;
|
|
344
|
+
|
|
345
|
+
//事件
|
|
346
|
+
com_sld.node.off("slide", com_sld['slideCall'], self)
|
|
347
|
+
tempData.skip = true;
|
|
348
|
+
const slideCall = (slider) => {
|
|
349
|
+
tempData.value = slider.progress
|
|
350
|
+
self.viewModel[sx] = tempData
|
|
351
|
+
data.event?.(self)
|
|
352
|
+
}
|
|
353
|
+
com_sld['slideCall'] = slideCall
|
|
354
|
+
com_sld.node.on('slide', slideCall, self);
|
|
355
|
+
break;
|
|
356
|
+
case 'cc.Toggle':
|
|
357
|
+
const com_tg = (com as Toggle);
|
|
358
|
+
if (data.reset) {
|
|
359
|
+
data.reset(self, value, com);
|
|
360
|
+
} else
|
|
361
|
+
if (value) com_tg.isChecked = Boolean(value);
|
|
362
|
+
|
|
363
|
+
//事件
|
|
364
|
+
com_tg.node.off(Toggle.EventType.TOGGLE, com_tg['toggleCall'], self)
|
|
365
|
+
tempData.skip = true;
|
|
366
|
+
const toggleCall = (toggle) => {
|
|
367
|
+
tempData.value = toggle.isChecked
|
|
368
|
+
self.viewModel[sx] = tempData
|
|
369
|
+
data.event?.(self)
|
|
370
|
+
}
|
|
371
|
+
com_tg['toggleCall'] = toggleCall
|
|
372
|
+
com_tg.node.on(Toggle.EventType.TOGGLE, toggleCall, self);
|
|
373
|
+
break;
|
|
374
|
+
case 'cc.EditBox':
|
|
375
|
+
const com_eb = (com as EditBox);
|
|
376
|
+
if (data.reset) {
|
|
377
|
+
data.reset(self, value, com);
|
|
378
|
+
} else
|
|
379
|
+
if (value) com_eb.string = value?.toString() || '';
|
|
380
|
+
|
|
381
|
+
//事件
|
|
382
|
+
com_eb.node.off("text-changed", com_eb['ebCall'], self)
|
|
383
|
+
tempData.skip = true;
|
|
384
|
+
const ebCall = (editbox: EditBox) => {
|
|
385
|
+
tempData.value = editbox.textLabel.string
|
|
386
|
+
self.viewModel[sx] = tempData
|
|
387
|
+
data.event?.(self)
|
|
388
|
+
}
|
|
389
|
+
com_eb['ebCall'] = ebCall
|
|
390
|
+
com_eb.node.on('text-changed', ebCall, self);
|
|
391
|
+
break;
|
|
392
|
+
case 'cc.ToggleContainer':
|
|
393
|
+
{
|
|
394
|
+
const com_tgc = (com as ToggleContainer);
|
|
395
|
+
if (data.reset) {
|
|
396
|
+
data.reset(self, value, com);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
//事件
|
|
400
|
+
if (com_tgc.checkEvents.length <= 0) {
|
|
401
|
+
const funcName = "onClick_ToggleContainer"
|
|
402
|
+
const clickEventHandler = new EventHandler();
|
|
403
|
+
clickEventHandler.target = self.node; // 这个 node 节点是你的事件处理代码组件所属的节点
|
|
404
|
+
clickEventHandler.component = js.getClassName(self)//delegate.constructor.name;// 这个是脚本类名
|
|
405
|
+
clickEventHandler.handler = funcName
|
|
406
|
+
self[funcName] = (toggle: Toggle) => {
|
|
407
|
+
tempData.skip = true;
|
|
408
|
+
tempData.value = com_tgc.toggleItems.indexOf(toggle)
|
|
409
|
+
self.viewModel[sx] = tempData
|
|
410
|
+
data.event?.(self)
|
|
411
|
+
}
|
|
412
|
+
com_tgc.checkEvents.push(clickEventHandler);
|
|
413
|
+
}
|
|
414
|
+
const tg = com_tgc.toggleItems[value]
|
|
415
|
+
if (tg)
|
|
416
|
+
tg.isChecked = true;
|
|
417
|
+
|
|
418
|
+
}
|
|
419
|
+
break;
|
|
420
|
+
|
|
421
|
+
case 'TableView':
|
|
422
|
+
{
|
|
423
|
+
|
|
424
|
+
const com_list = (com as TableView);
|
|
425
|
+
if (data.reset) { data.reset(self, value, com); }
|
|
426
|
+
|
|
427
|
+
// ✅ 关键:不要缓存 count,而是通过 dataPath 动态取值
|
|
428
|
+
const getLatestDataLength = () => {
|
|
429
|
+
const latestValue = self._getNestedValue(self, data.dataPath);
|
|
430
|
+
return Array.isArray(latestValue) ? latestValue.length : 0;
|
|
431
|
+
};
|
|
432
|
+
|
|
433
|
+
if (com_list.isInit) {
|
|
434
|
+
com_list.reload()
|
|
435
|
+
} else {
|
|
436
|
+
const cellForItemAt = (indexPath: IIndexPath, collectionView: ListView) => {
|
|
437
|
+
return data.cellForItemAt(self, indexPath, collectionView);
|
|
438
|
+
}
|
|
439
|
+
const numberOfItems = () => {
|
|
440
|
+
return getLatestDataLength()
|
|
441
|
+
}
|
|
442
|
+
const itemSize = () => {
|
|
443
|
+
return data.itemSize(self)
|
|
444
|
+
}
|
|
445
|
+
const moveFinish = (indexPath: IIndexPath) => {
|
|
446
|
+
data.moveFinish?.(self, indexPath)
|
|
447
|
+
}
|
|
448
|
+
const onTouchCellAt = (indexPath: IIndexPath) => {
|
|
449
|
+
data.onTouchCellAt?.(self, indexPath)
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
const classView = { cellForItemAt, numberOfItems, itemSize, moveFinish, onTouchCellAt }
|
|
453
|
+
com_list.onLoadFinish(() => {
|
|
454
|
+
com_list.init(classView);
|
|
455
|
+
com_list.reload()
|
|
456
|
+
})
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
break;
|
|
460
|
+
|
|
461
|
+
case 'YXCollectionView':
|
|
462
|
+
{
|
|
463
|
+
const com_list = (com as YXCollectionView);
|
|
464
|
+
// ✅ 关键:不要缓存 count,而是通过 dataPath 动态取值
|
|
465
|
+
const getLatestDataLength = () => {
|
|
466
|
+
const latestValue = self._getNestedValue(self, data.dataPath);
|
|
467
|
+
return Array.isArray(latestValue) ? latestValue.length : 0;
|
|
468
|
+
};
|
|
469
|
+
const table_collection = com_list
|
|
470
|
+
|
|
471
|
+
if (!table_collection.layout) {
|
|
472
|
+
const identifier = 'cell';
|
|
473
|
+
// 配置 layout 布局规则
|
|
474
|
+
// let layout = new YXFlowLayout()
|
|
475
|
+
// const column = 4
|
|
476
|
+
// layout.horizontalSpacing = 10
|
|
477
|
+
// layout.verticalSpacing = 10
|
|
478
|
+
// const width = 100
|
|
479
|
+
// const height = 163
|
|
480
|
+
// layout.itemSize = math.size(width, height)
|
|
481
|
+
table_collection.layout = data.layout()
|
|
482
|
+
// 注册列表内需要使用的 cell 节点类型
|
|
483
|
+
// 这个演示是通过编辑器绑定的,可以查看场景内 list 节点里的 register cells 配置
|
|
484
|
+
// this.table_collection.register('cell', () => instantiate('your cell prefab'))
|
|
485
|
+
// 确定列表内一共需要显示多少条内容
|
|
486
|
+
// table_collection.isCenterShow = false;//少于宽度,居中显示
|
|
487
|
+
table_collection.numberOfItems = () => getLatestDataLength()
|
|
488
|
+
table_collection.cellForItemAt = (indexPath, collectionView) => {
|
|
489
|
+
return data.cellForItemAt(self, indexPath, collectionView as any) // 返回这个节点给列表显示
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
table_collection.onTouchCellAt = (indexPath, collectionView) => {
|
|
493
|
+
// 通过 getVisibleNode 获取到点击的节点
|
|
494
|
+
//const cell = collectionView.getVisibleCellNode(indexPath)
|
|
495
|
+
data.onTouchCellAt?.(self, indexPath)
|
|
496
|
+
}
|
|
497
|
+
table_collection.onCellDisplay = (cell, indexPath) => { }
|
|
498
|
+
table_collection.onCellEndDisplay = (cell, indexPath) => { }
|
|
499
|
+
}
|
|
500
|
+
table_collection.reloadData()
|
|
501
|
+
}
|
|
502
|
+
break;
|
|
503
|
+
default:
|
|
504
|
+
console.error(`请检查类型: ${data.type}`);
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
}
|
|
508
|
+
// assets/cc-ex-component/core/ViewModel.ts
|
|
509
|
+
|
|
510
|
+
// ... 其他代码 ...
|
|
511
|
+
|
|
512
|
+
/**
|
|
513
|
+
* 响应式数据装饰器
|
|
514
|
+
* 自动将属性转为响应式对象,并使用属性名作为路径前缀
|
|
515
|
+
*/
|
|
516
|
+
export function BindViewModel(initialValue?: any) {
|
|
517
|
+
return function (target: any, propertyKey: string) {
|
|
518
|
+
const originalOnLoad = target.constructor.prototype.onLoad;
|
|
519
|
+
target.constructor.prototype.onLoad = function () {
|
|
520
|
+
// 获取初始值(支持传入或默认空对象)
|
|
521
|
+
const initValue = typeof initialValue === 'function'
|
|
522
|
+
? initialValue()
|
|
523
|
+
: (initialValue ?? {});
|
|
524
|
+
// 创建响应式对象
|
|
525
|
+
this[propertyKey] = this._makeReactive(initValue, propertyKey);
|
|
526
|
+
originalOnLoad?.call(this);
|
|
527
|
+
|
|
528
|
+
};
|
|
529
|
+
};
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
// 定义装饰器
|
|
533
|
+
export function Ref(target: any, propertyKey: string) {
|
|
534
|
+
const originalOnLoad = target.constructor.prototype.onLoad;
|
|
535
|
+
target.constructor.prototype.onLoad = function (this: any) {
|
|
536
|
+
this.initReferenceCollector();
|
|
537
|
+
this.defineProperty(propertyKey);
|
|
538
|
+
originalOnLoad?.call(this);
|
|
539
|
+
|
|
540
|
+
};
|
|
541
|
+
}
|
|
542
|
+
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
{
|
|
2
|
-
"ver": "4.0.24",
|
|
3
|
-
"importer": "typescript",
|
|
4
|
-
"imported": true,
|
|
5
|
-
"uuid": "
|
|
6
|
-
"files": [],
|
|
7
|
-
"subMetas": {},
|
|
8
|
-
"userData": {}
|
|
9
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"ver": "4.0.24",
|
|
3
|
+
"importer": "typescript",
|
|
4
|
+
"imported": true,
|
|
5
|
+
"uuid": "91193c30-a004-4bca-bfc0-45fb594eea0f",
|
|
6
|
+
"files": [],
|
|
7
|
+
"subMetas": {},
|
|
8
|
+
"userData": {}
|
|
9
|
+
}
|