v-uni-app-ui 1.0.4 → 1.0.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/README.md +62 -82
- package/dist/v-uni-app-ui.css +1 -0
- package/dist/v-uni-app-ui.es.js +6569 -0
- package/dist/v-uni-app-ui.umd.js +7 -0
- package/package.json +17 -5
- package/components/config/css/basic.scss +0 -19
- package/components/config/interface/basic-type.js +0 -16
- package/components/config/interface/components-interface.ts +0 -0
- package/components/config/interface/monitor/components/input-monitor.js +0 -0
- package/components/config/interface/monitor/property-monitor.ts +0 -136
- package/components/config/interface/props/basic-props.ts +0 -88
- package/components/config/interface/props/components/button-props.ts +0 -85
- package/components/config/interface/props/components/input-props.ts +0 -69
- package/components/config/interface/props/props-tools.ts +0 -64
- package/components/config/style/basic.js +0 -346
- package/components/config/style/component-registry.js +0 -142
- package/components/config/style/components/button-style.js +0 -160
- package/components/config/style/components/input-style.js +0 -98
- package/components/config/style/components-style.js +0 -622
- package/components/config/style/property-mapper.js +0 -377
- package/components/config/style/pseudo-processor.js +0 -213
- package/components/config.js +0 -123
- package/components/icon/iconfont.css +0 -87
- package/components/icon/iconfont.js +0 -1
- package/components/icon/iconfont.json +0 -135
- package/components/icon/iconfont.ttf +0 -0
- package/components/icon/iconfont.woff +0 -0
- package/components/icon/iconfont.woff2 +0 -0
- package/components/layout/v-card/v-card.vue +0 -108
- package/components/layout/v-grid/v-grid.vue +0 -162
- package/components/layout/v-icon-grid/v-icon-grid.vue +0 -195
- package/components/layout/v-infinite-scroll/v-infinite-scroll.vue +0 -172
- package/components/layout/v-list/v-list.vue +0 -43
- package/components/layout/v-row/v-row.vue +0 -142
- package/components/layout/v-waterfall/v-waterfall.vue +0 -79
- package/components/model/compound/v-checkbox-group/v-checkbox-group.vue +0 -96
- package/components/model/compound/v-console/v-console.js +0 -20
- package/components/model/compound/v-console/v-console.vue +0 -299
- package/components/model/compound/v-date-time/v-date-time.vue +0 -261
- package/components/model/compound/v-dialog/v-dialog.vue +0 -178
- package/components/model/compound/v-drum-select-picker/v-drum-select-picker.vue +0 -83
- package/components/model/compound/v-form/v-form.vue +0 -226
- package/components/model/compound/v-form-item/v-form-item.vue +0 -255
- package/components/model/compound/v-image/v-image.vue +0 -357
- package/components/model/compound/v-input-desensitize/v-input-desensitize.vue +0 -101
- package/components/model/compound/v-page/v-page.vue +0 -11
- package/components/model/compound/v-pages/v-pages.vue +0 -141
- package/components/model/compound/v-picker-list/v-picker-list.vue +0 -109
- package/components/model/compound/v-popup/v-popup.vue +0 -151
- package/components/model/compound/v-radio-group/v-radio-group.vue +0 -86
- package/components/model/compound/v-select-picker/v-select-picker.vue +0 -202
- package/components/model/compound/v-series-picker-list/v-series-picker-list.vue +0 -221
- package/components/model/compound/v-series-select-picker/v-series-select-picker.vue +0 -203
- package/components/model/compound/v-switch/v-switch.vue +0 -136
- package/components/model/compound/v-tabs-page/v-tabs-page.vue +0 -138
- package/components/model/native/v-badge/v-badge.vue +0 -143
- package/components/model/native/v-button/v-button.vue +0 -81
- package/components/model/native/v-carousel/v-carousel.vue +0 -138
- package/components/model/native/v-checkbox/v-checkbox.vue +0 -215
- package/components/model/native/v-collapse/v-collapse.vue +0 -190
- package/components/model/native/v-header-navigation-bar/v-header-navigation-bar.vue +0 -92
- package/components/model/native/v-input/v-input.vue +0 -163
- package/components/model/native/v-input-code/v-input-code.vue +0 -146
- package/components/model/native/v-loading/v-loading.vue +0 -206
- package/components/model/native/v-menu/v-menu.vue +0 -222
- package/components/model/native/v-menu-slide/v-menu-slide.vue +0 -364
- package/components/model/native/v-min-loading/v-min-loading.vue +0 -80
- package/components/model/native/v-null/v-null.vue +0 -97
- package/components/model/native/v-overlay/v-overlay.vue +0 -96
- package/components/model/native/v-pull-up-refresh/v-pull-up-refresh.vue +0 -157
- package/components/model/native/v-radio/v-radio.vue +0 -138
- package/components/model/native/v-scroll-list/v-scroll-list.vue +0 -169
- package/components/model/native/v-steps/v-steps.vue +0 -253
- package/components/model/native/v-table/v-table.vue +0 -203
- package/components/model/native/v-tabs/v-tabs.vue +0 -235
- package/components/model/native/v-tag/v-tag.vue +0 -206
- package/components/model/native/v-text/v-text.vue +0 -187
- package/components/model/native/v-textarea/v-textarea.vue +0 -178
- package/components/model/native/v-title/v-title.vue +0 -91
- package/components/model/native/v-toast/info.png +0 -0
- package/components/model/native/v-toast/success.png +0 -0
- package/components/model/native/v-toast/v-toast.vue +0 -198
- package/components/model/native/v-toast/warn.png +0 -0
- package/components/model/native/v-upload-file-button/v-upload-file-button.vue +0 -296
- package/components/model/native/v-video/v-video.vue +0 -175
- package/components/model/native/v-window/v-window.vue +0 -158
- package/components/utils/event-modifiers.ts +0 -139
- package/components/utils/validator.ts +0 -451
- package/index.js +0 -372
|
@@ -1,622 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
computed,
|
|
3
|
-
watch,
|
|
4
|
-
onUnmounted,
|
|
5
|
-
ref
|
|
6
|
-
} from 'vue'
|
|
7
|
-
import {
|
|
8
|
-
PropertyMapper
|
|
9
|
-
} from '@/components/config/style/property-mapper.js'
|
|
10
|
-
import {
|
|
11
|
-
getComponentStyleConfig
|
|
12
|
-
} from '@/components/config/style/component-registry.js'
|
|
13
|
-
import {
|
|
14
|
-
mergeWithPseudo
|
|
15
|
-
} from "@/components/config/style/pseudo-processor.js"
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* 增强的样式生成工具 - 使用属性映射器(支持父子分离样式)
|
|
19
|
-
*/
|
|
20
|
-
export const StyleGenerator = {
|
|
21
|
-
/**
|
|
22
|
-
* 根据组件名称和 props 生成分离的样式对象
|
|
23
|
-
*/
|
|
24
|
-
generateSeparatedStyle(componentName, props, customMaps = {}) {
|
|
25
|
-
const componentConfig = getComponentStyleConfig(componentName)
|
|
26
|
-
const mapper = new PropertyMapper(componentName, componentConfig, customMaps)
|
|
27
|
-
const style = mapper.mapAllProperties(props)
|
|
28
|
-
const separatedStyle = {
|
|
29
|
-
parent: {
|
|
30
|
-
...style
|
|
31
|
-
},
|
|
32
|
-
son: {}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
if (componentConfig && componentConfig.default && componentConfig.default.son) {
|
|
36
|
-
let sonConfig = componentConfig.default.son;
|
|
37
|
-
if (typeof sonConfig === 'function') {
|
|
38
|
-
sonConfig = sonConfig(props);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
if (sonConfig && typeof sonConfig === 'object') {
|
|
42
|
-
// 处理每个 son 元素的配置
|
|
43
|
-
for (const [elementName, elementConfig] of Object.entries(sonConfig)) {
|
|
44
|
-
if (elementConfig && typeof elementConfig === 'object') {
|
|
45
|
-
// 处理每个子元素的样式
|
|
46
|
-
separatedStyle.son[elementName] = this.processSonElementStyle(
|
|
47
|
-
elementConfig,
|
|
48
|
-
componentName,
|
|
49
|
-
props,
|
|
50
|
-
customMaps,
|
|
51
|
-
elementName
|
|
52
|
-
);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// 应用 son 相关的属性映射(保持向后兼容)
|
|
58
|
-
for (const [propName, propValue] of Object.entries(props)) {
|
|
59
|
-
if (mapper.shouldSkipProperty(propName)) {
|
|
60
|
-
continue
|
|
61
|
-
}
|
|
62
|
-
if (propName.startsWith('son')) {
|
|
63
|
-
const mappedStyle = mapper.mapProperty(propName, propValue, props)
|
|
64
|
-
if (mappedStyle && typeof mappedStyle === 'object') {
|
|
65
|
-
Object.assign(separatedStyle.son, mappedStyle)
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
return separatedStyle
|
|
72
|
-
},
|
|
73
|
-
/**
|
|
74
|
-
* 处理子元素样式,应用属性映射
|
|
75
|
-
*/
|
|
76
|
-
processSonElementStyle(elementConfig, componentName, props, customMaps, elementName) {
|
|
77
|
-
const result = {};
|
|
78
|
-
|
|
79
|
-
// 1. 先应用默认样式
|
|
80
|
-
if (elementConfig.default && typeof elementConfig.default === 'object') {
|
|
81
|
-
Object.assign(result, elementConfig.default);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// 2. 根据 props 应用对应的样式
|
|
85
|
-
for (const [propName, propValue] of Object.entries(props)) {
|
|
86
|
-
if (propValue === undefined || propValue === null) continue;
|
|
87
|
-
|
|
88
|
-
// 检查是否有该属性对应的配置
|
|
89
|
-
const propConfig = elementConfig[propName];
|
|
90
|
-
if (propConfig && propConfig[propValue]) {
|
|
91
|
-
Object.assign(result, propConfig[propValue]);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
return result;
|
|
96
|
-
},
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* 获取组件的分离伪类样式配置
|
|
101
|
-
*/
|
|
102
|
-
getSeparatedPseudoStyles(componentName, customMaps = {}) {
|
|
103
|
-
const componentConfig = getComponentStyleConfig(componentName)
|
|
104
|
-
|
|
105
|
-
const pseudoStyles = {
|
|
106
|
-
parent: {},
|
|
107
|
-
son: {}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
if (componentConfig && componentConfig.default) {
|
|
111
|
-
// 获取父容器的伪类配置
|
|
112
|
-
if (componentConfig.default._pseudo) {
|
|
113
|
-
pseudoStyles.parent = componentConfig.default._pseudo
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// 获取子元素的伪类配置
|
|
117
|
-
if (componentConfig.default.son) {
|
|
118
|
-
let sonConfig = componentConfig.default.son;
|
|
119
|
-
if (typeof sonConfig === 'function') {
|
|
120
|
-
// 如果 son 是函数,需要传入 props 来获取配置
|
|
121
|
-
sonConfig = sonConfig({});
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
if (sonConfig && typeof sonConfig === 'object') {
|
|
125
|
-
for (const [elementName, elementConfig] of Object.entries(sonConfig)) {
|
|
126
|
-
if (elementConfig && elementConfig._pseudo) {
|
|
127
|
-
pseudoStyles.son[elementName] = elementConfig._pseudo;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
return pseudoStyles
|
|
135
|
-
},
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* 根据伪类状态合并分离样式
|
|
139
|
-
*/
|
|
140
|
-
mergeSeparatedPseudo(baseStyles, pseudoStyles, pseudoKey, isActive, componentProps = {}) {
|
|
141
|
-
if (!isActive) {
|
|
142
|
-
return {
|
|
143
|
-
parent: {
|
|
144
|
-
...baseStyles.parent
|
|
145
|
-
},
|
|
146
|
-
son: {
|
|
147
|
-
...baseStyles.son
|
|
148
|
-
}
|
|
149
|
-
};
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
const result = {
|
|
153
|
-
parent: {
|
|
154
|
-
...baseStyles.parent
|
|
155
|
-
},
|
|
156
|
-
son: {
|
|
157
|
-
...baseStyles.son
|
|
158
|
-
}
|
|
159
|
-
};
|
|
160
|
-
|
|
161
|
-
// 合并父容器伪类样式
|
|
162
|
-
if (pseudoStyles.parent && pseudoStyles.parent[pseudoKey]) {
|
|
163
|
-
result.parent = this.mergeWithPseudo(
|
|
164
|
-
result.parent,
|
|
165
|
-
pseudoStyles.parent,
|
|
166
|
-
pseudoKey,
|
|
167
|
-
true,
|
|
168
|
-
componentProps
|
|
169
|
-
);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// 合并子元素伪类样式
|
|
173
|
-
if (pseudoStyles.son && Object.keys(pseudoStyles.son).length > 0) {
|
|
174
|
-
for (const [elementName, elementPseudo] of Object.entries(pseudoStyles.son)) {
|
|
175
|
-
if (elementPseudo && elementPseudo[pseudoKey]) {
|
|
176
|
-
// 确保子元素基础样式存在
|
|
177
|
-
if (!result.son[elementName]) {
|
|
178
|
-
result.son[elementName] = {};
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
// 合并子元素伪类样式
|
|
182
|
-
const mergedElementStyle = this.mergeWithPseudo(
|
|
183
|
-
result.son[elementName],
|
|
184
|
-
elementPseudo,
|
|
185
|
-
pseudoKey,
|
|
186
|
-
true,
|
|
187
|
-
componentProps
|
|
188
|
-
);
|
|
189
|
-
|
|
190
|
-
result.son[elementName] = mergedElementStyle;
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
return result;
|
|
196
|
-
},
|
|
197
|
-
|
|
198
|
-
/**
|
|
199
|
-
* 根据伪类状态合并样式,支持关联样式
|
|
200
|
-
*/
|
|
201
|
-
mergeWithPseudo(baseStyle, pseudoStyles, pseudoKey, isActive, componentProps = {}) {
|
|
202
|
-
return mergeWithPseudo(
|
|
203
|
-
baseStyle,
|
|
204
|
-
pseudoStyles,
|
|
205
|
-
pseudoKey,
|
|
206
|
-
isActive,
|
|
207
|
-
componentProps
|
|
208
|
-
);
|
|
209
|
-
},
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
/**
|
|
213
|
-
* 生成内联样式对象(兼容原有接口)
|
|
214
|
-
*/
|
|
215
|
-
generateInlineStyle(componentName, props, customMaps = {}) {
|
|
216
|
-
const {
|
|
217
|
-
parent
|
|
218
|
-
} = this.generateSeparatedStyle(componentName, props, customMaps)
|
|
219
|
-
return this.toInlineStyle(parent)
|
|
220
|
-
},
|
|
221
|
-
|
|
222
|
-
/**
|
|
223
|
-
* 生成分离的内联样式对象
|
|
224
|
-
*/
|
|
225
|
-
generateSeparatedInlineStyle(componentName, props, customMaps = {}) {
|
|
226
|
-
const separatedStyle = this.generateSeparatedStyle(componentName, props, customMaps);
|
|
227
|
-
const processedSon = {};
|
|
228
|
-
|
|
229
|
-
// 处理 son 对象的每个元素
|
|
230
|
-
for (const [elementName, elementStyle] of Object.entries(separatedStyle.son)) {
|
|
231
|
-
processedSon[elementName] = this.toInlineStyle(elementStyle);
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
return {
|
|
235
|
-
parent: this.toInlineStyle(separatedStyle.parent),
|
|
236
|
-
son: processedSon
|
|
237
|
-
}
|
|
238
|
-
},
|
|
239
|
-
|
|
240
|
-
/**
|
|
241
|
-
* 获取伪类样式配置(兼容原有接口)
|
|
242
|
-
*/
|
|
243
|
-
getPseudoStyles(componentName, customMaps = {}) {
|
|
244
|
-
const {
|
|
245
|
-
parent
|
|
246
|
-
} = this.getSeparatedPseudoStyles(componentName, customMaps)
|
|
247
|
-
return parent
|
|
248
|
-
},
|
|
249
|
-
|
|
250
|
-
/**
|
|
251
|
-
* 将伪类样式转换为 SCSS 变量
|
|
252
|
-
*/
|
|
253
|
-
pseudoToScssVariables(pseudoStyles) {
|
|
254
|
-
if (!pseudoStyles || typeof pseudoStyles !== 'object') {
|
|
255
|
-
return ''
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
let scss = ''
|
|
259
|
-
for (const [pseudoKey, styles] of Object.entries(pseudoStyles)) {
|
|
260
|
-
// 转换伪类键名(--hover -> hover)
|
|
261
|
-
const pseudoName = pseudoKey.replace('--', '')
|
|
262
|
-
scss += `// ${pseudoName} 伪类样式\n`
|
|
263
|
-
|
|
264
|
-
for (const [property, value] of Object.entries(styles)) {
|
|
265
|
-
// 生成 SCSS 变量名
|
|
266
|
-
const varName = `--${property.replace(/([A-Z])/g, '-$1').toLowerCase()}`
|
|
267
|
-
scss += `${varName}: ${value};\n`
|
|
268
|
-
}
|
|
269
|
-
scss += '\n'
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
return scss
|
|
273
|
-
},
|
|
274
|
-
|
|
275
|
-
/**
|
|
276
|
-
* 生成 SCSS 伪类代码块
|
|
277
|
-
*/
|
|
278
|
-
generatePseudoScss(pseudoStyles) {
|
|
279
|
-
if (!pseudoStyles || typeof pseudoStyles !== 'object') {
|
|
280
|
-
return ''
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
let scss = ''
|
|
284
|
-
for (const [pseudoKey, styles] of Object.entries(pseudoStyles)) {
|
|
285
|
-
// 转换伪类键名(--hover -> :hover)
|
|
286
|
-
const pseudoClass = pseudoKey.replace('--', ':')
|
|
287
|
-
|
|
288
|
-
// 生成 SCSS 代码块
|
|
289
|
-
scss += ` ${pseudoClass} {\n`
|
|
290
|
-
for (const [property, value] of Object.entries(styles)) {
|
|
291
|
-
scss += ` ${property}: ${value};\n`
|
|
292
|
-
}
|
|
293
|
-
scss += ` }\n`
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
return scss
|
|
297
|
-
},
|
|
298
|
-
|
|
299
|
-
/**
|
|
300
|
-
* 生成 CSS 字符串
|
|
301
|
-
*/
|
|
302
|
-
generateCSS(componentName, props, customMaps = {}) {
|
|
303
|
-
const styleObj = this.generateSeparatedStyle(componentName, props, customMaps)
|
|
304
|
-
return this.toCSS(styleObj.parent)
|
|
305
|
-
},
|
|
306
|
-
|
|
307
|
-
/**
|
|
308
|
-
* 生成类名数组
|
|
309
|
-
*/
|
|
310
|
-
generateClassNames(componentName, props) {
|
|
311
|
-
const classes = []
|
|
312
|
-
|
|
313
|
-
// 添加自定义类名
|
|
314
|
-
if (props.className) {
|
|
315
|
-
classes.push(props.className)
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
// 遍历属性生成类名
|
|
319
|
-
for (const [propName, propValue] of Object.entries(props)) {
|
|
320
|
-
// 跳过不需要生成类名的属性
|
|
321
|
-
if (this.shouldSkipClassProperty(propName)) {
|
|
322
|
-
continue
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
// 布尔属性
|
|
326
|
-
if (typeof propValue === 'boolean' || typeof propValue === 'number' && propValue) {
|
|
327
|
-
classes.push(`${componentName}--${propName}`)
|
|
328
|
-
}
|
|
329
|
-
// 字符串/数字属性
|
|
330
|
-
else if (typeof propValue === 'string' && propValue.trim()) {
|
|
331
|
-
classes.push(`${componentName}--${propName}--${propValue}`)
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
return classes.filter(Boolean)
|
|
336
|
-
},
|
|
337
|
-
|
|
338
|
-
/**
|
|
339
|
-
* 检查是否应该跳过生成类名的属性
|
|
340
|
-
*/
|
|
341
|
-
shouldSkipClassProperty(propName) {
|
|
342
|
-
const skipProps = [
|
|
343
|
-
'id', 'key', 'ref', 'class', 'className', 'style',
|
|
344
|
-
'modelValue', 'onUpdate:modelValue', 'children',
|
|
345
|
-
'stabilizationTime', 'intervalUpdateTime', 'degressionTime'
|
|
346
|
-
]
|
|
347
|
-
|
|
348
|
-
// 跳过事件处理器
|
|
349
|
-
if (propName.startsWith('on') || propName.startsWith('@')) {
|
|
350
|
-
return true
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
return skipProps.includes(propName)
|
|
354
|
-
},
|
|
355
|
-
|
|
356
|
-
/**
|
|
357
|
-
* 将样式对象转换为 CSS 字符串
|
|
358
|
-
*/
|
|
359
|
-
toCSS(styleObject) {
|
|
360
|
-
if (!styleObject || typeof styleObject !== 'object') {
|
|
361
|
-
return ''
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
return Object.entries(styleObject)
|
|
365
|
-
.map(([key, value]) => {
|
|
366
|
-
if (value === undefined || value === null) return ''
|
|
367
|
-
return `${key}: ${value};`
|
|
368
|
-
})
|
|
369
|
-
.filter(Boolean)
|
|
370
|
-
.join(' ')
|
|
371
|
-
},
|
|
372
|
-
|
|
373
|
-
/**
|
|
374
|
-
* 将样式对象转换为内联样式对象(驼峰命名)
|
|
375
|
-
*/
|
|
376
|
-
toInlineStyle(styleObject) {
|
|
377
|
-
if (!styleObject || typeof styleObject !== 'object') {
|
|
378
|
-
return {}
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
return Object.entries(styleObject).reduce((result, [key, value]) => {
|
|
382
|
-
if (value === undefined || value === null) return result
|
|
383
|
-
|
|
384
|
-
const camelKey = key.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase())
|
|
385
|
-
result[camelKey] = value
|
|
386
|
-
return result
|
|
387
|
-
}, {})
|
|
388
|
-
},
|
|
389
|
-
|
|
390
|
-
/**
|
|
391
|
-
* 合并多个样式对象
|
|
392
|
-
*/
|
|
393
|
-
mergeStyles(...styleObjects) {
|
|
394
|
-
return styleObjects.reduce((result, current) => {
|
|
395
|
-
if (!current) return result
|
|
396
|
-
return {
|
|
397
|
-
...result,
|
|
398
|
-
...current
|
|
399
|
-
}
|
|
400
|
-
}, {})
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
/**
|
|
405
|
-
* 组件样式钩子(支持父子分离样式)
|
|
406
|
-
*/
|
|
407
|
-
export function useComponentStyle(componentName, props, customMaps = {}) {
|
|
408
|
-
const isHovered = ref(false);
|
|
409
|
-
const isFocused = ref(false);
|
|
410
|
-
const isActive = ref(false);
|
|
411
|
-
const isDisabled = ref(false);
|
|
412
|
-
|
|
413
|
-
/* 生成分离的基础样式 */
|
|
414
|
-
const baseSeparatedStyle = computed(() => {
|
|
415
|
-
return StyleGenerator.generateSeparatedInlineStyle(componentName, props, customMaps);
|
|
416
|
-
});
|
|
417
|
-
|
|
418
|
-
/* 获取分离的伪类样式配置 */
|
|
419
|
-
const separatedPseudoStyles = computed(() => {
|
|
420
|
-
return StyleGenerator.getSeparatedPseudoStyles(componentName, customMaps);
|
|
421
|
-
});
|
|
422
|
-
|
|
423
|
-
/* 根据伪类状态计算最终分离样式 */
|
|
424
|
-
const separatedStyle = computed(() => {
|
|
425
|
-
let currentStyles = {
|
|
426
|
-
parent: {
|
|
427
|
-
...baseSeparatedStyle.value.parent
|
|
428
|
-
},
|
|
429
|
-
son: {
|
|
430
|
-
...baseSeparatedStyle.value.son
|
|
431
|
-
}
|
|
432
|
-
};
|
|
433
|
-
|
|
434
|
-
// 按照优先级合并伪类样式
|
|
435
|
-
if (isDisabled.value) {
|
|
436
|
-
currentStyles = StyleGenerator.mergeSeparatedPseudo(
|
|
437
|
-
currentStyles,
|
|
438
|
-
separatedPseudoStyles.value,
|
|
439
|
-
'--disabled',
|
|
440
|
-
true,
|
|
441
|
-
props
|
|
442
|
-
);
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
// 2. focus 状态
|
|
446
|
-
if (isFocused.value) {
|
|
447
|
-
currentStyles = StyleGenerator.mergeSeparatedPseudo(
|
|
448
|
-
currentStyles,
|
|
449
|
-
separatedPseudoStyles.value,
|
|
450
|
-
'--focus',
|
|
451
|
-
true,
|
|
452
|
-
props
|
|
453
|
-
);
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
// 3. hover 状态(只在非 disabled 时生效)
|
|
457
|
-
if (isHovered.value && !isDisabled.value) {
|
|
458
|
-
currentStyles = StyleGenerator.mergeSeparatedPseudo(
|
|
459
|
-
currentStyles,
|
|
460
|
-
separatedPseudoStyles.value,
|
|
461
|
-
'--hover',
|
|
462
|
-
true,
|
|
463
|
-
props
|
|
464
|
-
);
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
// 4. active 状态
|
|
468
|
-
if (isActive.value) {
|
|
469
|
-
currentStyles = StyleGenerator.mergeSeparatedPseudo(
|
|
470
|
-
currentStyles,
|
|
471
|
-
separatedPseudoStyles.value,
|
|
472
|
-
'--active',
|
|
473
|
-
true,
|
|
474
|
-
props
|
|
475
|
-
);
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
return currentStyles;
|
|
479
|
-
});
|
|
480
|
-
|
|
481
|
-
/* 兼容原有接口的样式 */
|
|
482
|
-
const computedStyle = computed(() => {
|
|
483
|
-
const {
|
|
484
|
-
son,
|
|
485
|
-
...rest
|
|
486
|
-
} = separatedStyle.value.parent;
|
|
487
|
-
return rest;
|
|
488
|
-
});
|
|
489
|
-
|
|
490
|
-
const sonStyle = computed(() => separatedStyle.value.son);
|
|
491
|
-
|
|
492
|
-
/* 生成类名 */
|
|
493
|
-
const computedClasses = computed(() => {
|
|
494
|
-
const classes = StyleGenerator.generateClassNames(componentName, props)
|
|
495
|
-
|
|
496
|
-
// 添加伪类状态类名
|
|
497
|
-
if (isHovered.value) classes.push(`${componentName}--hover`);
|
|
498
|
-
if (isFocused.value) classes.push(`${componentName}--focus`);
|
|
499
|
-
if (isActive.value) classes.push(`${componentName}--active`);
|
|
500
|
-
if (isDisabled.value) classes.push(`${componentName}--disabled`);
|
|
501
|
-
|
|
502
|
-
return classes
|
|
503
|
-
})
|
|
504
|
-
|
|
505
|
-
/* 生成css样式(字符串) */
|
|
506
|
-
const computedCSS = computed(() => {
|
|
507
|
-
return StyleGenerator.toCSS(computedStyle.value)
|
|
508
|
-
})
|
|
509
|
-
|
|
510
|
-
/* 生成 SCSS 变量 */
|
|
511
|
-
const scssVariables = computed(() => {
|
|
512
|
-
return StyleGenerator.pseudoToScssVariables(separatedPseudoStyles.value.parent)
|
|
513
|
-
})
|
|
514
|
-
|
|
515
|
-
/* 生成 SCSS 代码块 */
|
|
516
|
-
const scssCode = computed(() => {
|
|
517
|
-
return StyleGenerator.generatePseudoScss(separatedPseudoStyles.value.parent)
|
|
518
|
-
})
|
|
519
|
-
|
|
520
|
-
/* 实时监控 props 变化 */
|
|
521
|
-
const stop = watch(
|
|
522
|
-
() => props.style,
|
|
523
|
-
newVal => {
|
|
524
|
-
// 更新父容器样式
|
|
525
|
-
Object.assign(baseSeparatedStyle.value.parent, newVal);
|
|
526
|
-
}, {
|
|
527
|
-
deep: true,
|
|
528
|
-
immediate: true
|
|
529
|
-
}
|
|
530
|
-
)
|
|
531
|
-
|
|
532
|
-
// 监听 sonStyle 变化
|
|
533
|
-
watch(() => props.sonStyle, (newVal) => {
|
|
534
|
-
if (newVal) {
|
|
535
|
-
Object.assign(baseSeparatedStyle.value.son, newVal);
|
|
536
|
-
}
|
|
537
|
-
}, {
|
|
538
|
-
immediate: true
|
|
539
|
-
});
|
|
540
|
-
|
|
541
|
-
// 监听 disabled 状态
|
|
542
|
-
watch(() => props.disabled, (disabled) => {
|
|
543
|
-
isDisabled.value = disabled;
|
|
544
|
-
}, {
|
|
545
|
-
immediate: true
|
|
546
|
-
});
|
|
547
|
-
|
|
548
|
-
onUnmounted(stop)
|
|
549
|
-
|
|
550
|
-
return {
|
|
551
|
-
// 分离样式
|
|
552
|
-
separatedStyle,
|
|
553
|
-
// 父容器样式(兼容原有)
|
|
554
|
-
style: computedStyle,
|
|
555
|
-
// 子元素样式
|
|
556
|
-
sonStyle,
|
|
557
|
-
classes: computedClasses,
|
|
558
|
-
css: computedCSS,
|
|
559
|
-
pseudo: separatedPseudoStyles,
|
|
560
|
-
scssVariables: scssVariables,
|
|
561
|
-
scssCode: scssCode,
|
|
562
|
-
stopWatchStyle: stop,
|
|
563
|
-
|
|
564
|
-
// 伪类状态控制函数
|
|
565
|
-
hover: (state) => {
|
|
566
|
-
isHovered.value = state;
|
|
567
|
-
},
|
|
568
|
-
focus: (state) => {
|
|
569
|
-
isFocused.value = state;
|
|
570
|
-
},
|
|
571
|
-
active: (state) => {
|
|
572
|
-
isActive.value = state;
|
|
573
|
-
},
|
|
574
|
-
disabled: (state) => {
|
|
575
|
-
isDisabled.value = state;
|
|
576
|
-
},
|
|
577
|
-
resetPseudoStates: () => {
|
|
578
|
-
isHovered.value = false;
|
|
579
|
-
isFocused.value = false;
|
|
580
|
-
isActive.value = false;
|
|
581
|
-
// disabled 状态由 props.disabled 控制,不重置
|
|
582
|
-
},
|
|
583
|
-
|
|
584
|
-
// 当前状态值(用于调试或外部访问)
|
|
585
|
-
states: {
|
|
586
|
-
hover: isHovered,
|
|
587
|
-
focus: isFocused,
|
|
588
|
-
active: isActive,
|
|
589
|
-
disabled: isDisabled
|
|
590
|
-
},
|
|
591
|
-
|
|
592
|
-
// 原始生成器方法
|
|
593
|
-
generateStyle: (customProps = {}) =>
|
|
594
|
-
StyleGenerator.generateSeparatedStyle(componentName, {
|
|
595
|
-
...props,
|
|
596
|
-
...customProps
|
|
597
|
-
}, customMaps),
|
|
598
|
-
|
|
599
|
-
generateCSS: (customProps = {}) =>
|
|
600
|
-
StyleGenerator.generateCSS(componentName, {
|
|
601
|
-
...props,
|
|
602
|
-
...customProps
|
|
603
|
-
}, customMaps),
|
|
604
|
-
|
|
605
|
-
// 伪类样式相关方法
|
|
606
|
-
getPseudoStyles: () => StyleGenerator.getSeparatedPseudoStyles(componentName, customMaps),
|
|
607
|
-
pseudoToScssVariables: () => StyleGenerator.pseudoToScssVariables(separatedPseudoStyles.value.parent),
|
|
608
|
-
generatePseudoScss: () => StyleGenerator.generatePseudoScss(separatedPseudoStyles.value.parent),
|
|
609
|
-
|
|
610
|
-
// 工具方法
|
|
611
|
-
mergeStyles: StyleGenerator.mergeStyles,
|
|
612
|
-
toCSS: StyleGenerator.toCSS,
|
|
613
|
-
toInlineStyle: StyleGenerator.toInlineStyle
|
|
614
|
-
}
|
|
615
|
-
}
|
|
616
|
-
|
|
617
|
-
/**
|
|
618
|
-
* 快捷方式:为常用组件创建特定的钩子
|
|
619
|
-
*/
|
|
620
|
-
export function useButtonStyle(props, customMaps = {}) {
|
|
621
|
-
return useComponentStyle('button', props, customMaps)
|
|
622
|
-
}
|