@mpxjs/webpack-plugin 2.10.22 → 2.10.24-test.1
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/lib/loader.js +2 -0
- package/lib/platform/style/wx/index.js +395 -104
- package/lib/react/index.js +3 -1
- package/lib/react/processTemplate.js +3 -1
- package/lib/react/style-helper.js +6 -6
- package/lib/runtime/components/react/animationHooks/index.ts +7 -3
- package/lib/runtime/components/react/dist/animationHooks/index.d.ts +0 -2
- package/lib/runtime/components/react/dist/animationHooks/index.js +6 -1
- package/lib/runtime/components/react/dist/event.config.d.ts +2 -6
- package/lib/runtime/components/react/dist/event.config.js +28 -24
- package/lib/runtime/components/react/dist/getInnerListeners.d.ts +1 -1
- package/lib/runtime/components/react/dist/getInnerListeners.js +74 -56
- package/lib/runtime/components/react/dist/mpx-button.d.ts +1 -1
- package/lib/runtime/components/react/dist/mpx-button.jsx +16 -9
- package/lib/runtime/components/react/dist/mpx-camera.d.ts +0 -1
- package/lib/runtime/components/react/dist/mpx-camera.jsx +1 -2
- package/lib/runtime/components/react/dist/mpx-canvas/index.d.ts +0 -1
- package/lib/runtime/components/react/dist/mpx-canvas/index.jsx +1 -2
- package/lib/runtime/components/react/dist/mpx-canvas/utils.d.ts +1 -1
- package/lib/runtime/components/react/dist/mpx-checkbox-group.d.ts +0 -1
- package/lib/runtime/components/react/dist/mpx-checkbox-group.jsx +3 -4
- package/lib/runtime/components/react/dist/mpx-checkbox.d.ts +1 -1
- package/lib/runtime/components/react/dist/mpx-checkbox.jsx +8 -9
- package/lib/runtime/components/react/dist/mpx-form.d.ts +1 -1
- package/lib/runtime/components/react/dist/mpx-form.jsx +5 -5
- package/lib/runtime/components/react/dist/mpx-icon/index.d.ts +0 -1
- package/lib/runtime/components/react/dist/mpx-icon/index.jsx +2 -2
- package/lib/runtime/components/react/dist/mpx-image.d.ts +0 -1
- package/lib/runtime/components/react/dist/mpx-image.jsx +59 -43
- package/lib/runtime/components/react/dist/mpx-input.d.ts +0 -1
- package/lib/runtime/components/react/dist/mpx-input.jsx +2 -2
- package/lib/runtime/components/react/dist/mpx-label.d.ts +1 -1
- package/lib/runtime/components/react/dist/mpx-label.jsx +5 -6
- package/lib/runtime/components/react/dist/mpx-movable-area.d.ts +0 -1
- package/lib/runtime/components/react/dist/mpx-movable-area.jsx +3 -3
- package/lib/runtime/components/react/dist/mpx-movable-view.d.ts +1 -1
- package/lib/runtime/components/react/dist/mpx-movable-view.jsx +6 -6
- package/lib/runtime/components/react/dist/mpx-picker-view/index.d.ts +1 -1
- package/lib/runtime/components/react/dist/mpx-picker-view/index.jsx +5 -7
- package/lib/runtime/components/react/dist/mpx-picker-view-column/index.d.ts +0 -1
- package/lib/runtime/components/react/dist/mpx-picker-view-column/index.jsx +2 -2
- package/lib/runtime/components/react/dist/mpx-progress.d.ts +0 -1
- package/lib/runtime/components/react/dist/mpx-progress.jsx +1 -2
- package/lib/runtime/components/react/dist/mpx-radio-group.d.ts +0 -1
- package/lib/runtime/components/react/dist/mpx-radio-group.jsx +3 -4
- package/lib/runtime/components/react/dist/mpx-radio.d.ts +1 -1
- package/lib/runtime/components/react/dist/mpx-radio.jsx +8 -9
- package/lib/runtime/components/react/dist/mpx-rich-text/index.d.ts +0 -1
- package/lib/runtime/components/react/dist/mpx-rich-text/index.jsx +1 -2
- package/lib/runtime/components/react/dist/mpx-scroll-view.d.ts +1 -1
- package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +6 -6
- package/lib/runtime/components/react/dist/mpx-simple-text.jsx +36 -31
- package/lib/runtime/components/react/dist/mpx-simple-view.d.ts +4 -2
- package/lib/runtime/components/react/dist/mpx-simple-view.jsx +24 -17
- package/lib/runtime/components/react/dist/mpx-slider.d.ts +0 -1
- package/lib/runtime/components/react/dist/mpx-slider.jsx +6 -6
- package/lib/runtime/components/react/dist/mpx-sticky-header.d.ts +1 -1
- package/lib/runtime/components/react/dist/mpx-sticky-header.jsx +5 -5
- package/lib/runtime/components/react/dist/mpx-sticky-section.d.ts +1 -1
- package/lib/runtime/components/react/dist/mpx-sticky-section.jsx +6 -6
- package/lib/runtime/components/react/dist/mpx-swiper-item.d.ts +1 -1
- package/lib/runtime/components/react/dist/mpx-swiper-item.jsx +5 -5
- package/lib/runtime/components/react/dist/mpx-swiper.d.ts +1 -1
- package/lib/runtime/components/react/dist/mpx-swiper.jsx +4 -7
- package/lib/runtime/components/react/dist/mpx-switch.d.ts +0 -1
- package/lib/runtime/components/react/dist/mpx-switch.jsx +1 -2
- package/lib/runtime/components/react/dist/mpx-text.d.ts +0 -1
- package/lib/runtime/components/react/dist/mpx-text.jsx +44 -40
- package/lib/runtime/components/react/dist/mpx-video.d.ts +0 -1
- package/lib/runtime/components/react/dist/mpx-video.jsx +4 -4
- package/lib/runtime/components/react/dist/mpx-view.d.ts +2 -1
- package/lib/runtime/components/react/dist/mpx-view.jsx +229 -128
- package/lib/runtime/components/react/dist/mpx-web-view.jsx +5 -1
- package/lib/runtime/components/react/dist/namedColorSet.d.ts +2 -0
- package/lib/runtime/components/react/dist/namedColorSet.js +149 -0
- package/lib/runtime/components/react/dist/utils.d.ts +73 -69
- package/lib/runtime/components/react/dist/utils.jsx +1295 -442
- package/lib/runtime/components/react/event.config.ts +32 -25
- package/lib/runtime/components/react/getInnerListeners.ts +84 -60
- package/lib/runtime/components/react/mpx-button.tsx +18 -16
- package/lib/runtime/components/react/mpx-camera.tsx +0 -3
- package/lib/runtime/components/react/mpx-canvas/index.tsx +1 -3
- package/lib/runtime/components/react/mpx-canvas/utils.tsx +3 -1
- package/lib/runtime/components/react/mpx-checkbox-group.tsx +2 -6
- package/lib/runtime/components/react/mpx-checkbox.tsx +9 -11
- package/lib/runtime/components/react/mpx-form.tsx +6 -6
- package/lib/runtime/components/react/mpx-icon/index.tsx +1 -3
- package/lib/runtime/components/react/mpx-image.tsx +65 -54
- package/lib/runtime/components/react/mpx-input.tsx +1 -3
- package/lib/runtime/components/react/mpx-label.tsx +6 -8
- package/lib/runtime/components/react/mpx-movable-area.tsx +3 -4
- package/lib/runtime/components/react/mpx-movable-view.tsx +7 -7
- package/lib/runtime/components/react/mpx-picker-view/index.tsx +6 -8
- package/lib/runtime/components/react/mpx-picker-view-column/index.tsx +2 -4
- package/lib/runtime/components/react/mpx-progress.tsx +0 -3
- package/lib/runtime/components/react/mpx-radio-group.tsx +2 -6
- package/lib/runtime/components/react/mpx-radio.tsx +9 -11
- package/lib/runtime/components/react/mpx-rich-text/index.tsx +0 -3
- package/lib/runtime/components/react/mpx-scroll-view.tsx +7 -7
- package/lib/runtime/components/react/mpx-simple-text.tsx +36 -38
- package/lib/runtime/components/react/mpx-simple-view.tsx +29 -17
- package/lib/runtime/components/react/mpx-slider.tsx +15 -10
- package/lib/runtime/components/react/mpx-sticky-header.tsx +6 -6
- package/lib/runtime/components/react/mpx-sticky-section.tsx +7 -7
- package/lib/runtime/components/react/mpx-swiper-item.tsx +6 -6
- package/lib/runtime/components/react/mpx-swiper.tsx +5 -8
- package/lib/runtime/components/react/mpx-switch.tsx +0 -3
- package/lib/runtime/components/react/mpx-text.tsx +46 -49
- package/lib/runtime/components/react/mpx-video.tsx +3 -5
- package/lib/runtime/components/react/mpx-view.tsx +250 -141
- package/lib/runtime/components/react/mpx-web-view.tsx +8 -3
- package/lib/runtime/components/react/namedColorSet.ts +150 -0
- package/lib/runtime/components/react/types/getInnerListeners.d.ts +21 -1
- package/lib/runtime/components/react/types/global.d.ts +1 -0
- package/lib/runtime/components/react/utils.tsx +1347 -539
- package/lib/runtime/i18n.wxs +15 -9
- package/lib/style-compiler/strip-conditional.js +19 -4
- package/lib/template-compiler/compiler.js +5 -1
- package/lib/utils/source-location.js +9 -13
- package/lib/web/index.js +3 -1
- package/lib/web/processTemplate.js +3 -1
- package/package.json +5 -4
- package/LICENSE +0 -433
|
@@ -4,16 +4,17 @@
|
|
|
4
4
|
* ✔ hover-start-time
|
|
5
5
|
* ✔ hover-stay-time
|
|
6
6
|
*/
|
|
7
|
-
import { View,
|
|
8
|
-
import { useRef, useState, useEffect, forwardRef, ReactNode, JSX, createElement } from 'react'
|
|
7
|
+
import { View, NativeSyntheticEvent, ViewProps, ImageStyle, StyleSheet, Image, LayoutChangeEvent } from 'react-native'
|
|
8
|
+
import { useRef, useState, useEffect, useMemo, forwardRef, ReactNode, JSX, createElement } from 'react'
|
|
9
9
|
import useInnerProps from './getInnerListeners'
|
|
10
10
|
import Animated from 'react-native-reanimated'
|
|
11
11
|
import useAnimationHooks, { AnimationType } from './animationHooks/index'
|
|
12
12
|
import type { AnimationProp } from './animationHooks/utils'
|
|
13
13
|
import { ExtendedViewStyle } from './types/common'
|
|
14
14
|
import useNodesRef, { HandlerRef } from './useNodesRef'
|
|
15
|
-
import { parseUrl,
|
|
16
|
-
import {
|
|
15
|
+
import { parseUrl, percentRegExp, splitStyle, splitProps, useTransformStyle, wrapChildren, useLayout, renderImage, pickStyle, extendObject, useHover, useTextPassThrough } from './utils'
|
|
16
|
+
import { TextPassThroughContextValue } from './context'
|
|
17
|
+
import { error, warn, hasOwn } from '@mpxjs/utils'
|
|
17
18
|
import * as perf from '@mpxjs/perf'
|
|
18
19
|
import LinearGradient from 'react-native-linear-gradient'
|
|
19
20
|
import { GestureDetector, PanGesture } from 'react-native-gesture-handler'
|
|
@@ -27,9 +28,9 @@ export interface _ViewProps extends ViewProps {
|
|
|
27
28
|
'hover-start-time'?: number
|
|
28
29
|
'hover-stay-time'?: number
|
|
29
30
|
'enable-background'?: boolean
|
|
31
|
+
'enable-text-pass-through'?: boolean
|
|
30
32
|
'enable-var'?: boolean
|
|
31
33
|
'enable-fast-image'?: boolean
|
|
32
|
-
'external-var-context'?: Record<string, any>
|
|
33
34
|
'parent-font-size'?: number
|
|
34
35
|
'parent-width'?: number
|
|
35
36
|
'parent-height'?: number
|
|
@@ -41,8 +42,6 @@ export interface _ViewProps extends ViewProps {
|
|
|
41
42
|
catchtransitionend?: (event: NativeSyntheticEvent<TouchEvent> | unknown) => void
|
|
42
43
|
}
|
|
43
44
|
|
|
44
|
-
type Handler = (...args: any[]) => void
|
|
45
|
-
|
|
46
45
|
type Size = {
|
|
47
46
|
width: number
|
|
48
47
|
height: number
|
|
@@ -84,12 +83,16 @@ type ImageProps = {
|
|
|
84
83
|
style: ImageStyle,
|
|
85
84
|
src?: string,
|
|
86
85
|
source?: { uri: string },
|
|
87
|
-
colors
|
|
86
|
+
colors?: Array<string>,
|
|
88
87
|
locations?: Array<number>
|
|
89
88
|
angle?: number
|
|
90
89
|
resizeMode?: 'cover' | 'stretch'
|
|
91
90
|
}
|
|
92
91
|
|
|
92
|
+
type LinearImageProps = ImageProps & {
|
|
93
|
+
colors: Array<string>
|
|
94
|
+
}
|
|
95
|
+
|
|
93
96
|
const linearMap = new Map([
|
|
94
97
|
['top', 0],
|
|
95
98
|
['bottom', 180],
|
|
@@ -97,6 +100,19 @@ const linearMap = new Map([
|
|
|
97
100
|
['right', 90]
|
|
98
101
|
])
|
|
99
102
|
|
|
103
|
+
const FLEX_DEFAULT_STYLE: ExtendedViewStyle = {
|
|
104
|
+
flexDirection: 'row',
|
|
105
|
+
flexBasis: 'auto',
|
|
106
|
+
flexShrink: 1,
|
|
107
|
+
flexWrap: 'nowrap'
|
|
108
|
+
}
|
|
109
|
+
// 用户传入 flex shorthand 时使用的精简版(裁掉 flexBasis/flexShrink)
|
|
110
|
+
// 避免 number 形式 flex:1 被 default flexBasis:'auto' 反向覆盖
|
|
111
|
+
const FLEX_DEFAULT_STYLE_TRIMMED: ExtendedViewStyle = {
|
|
112
|
+
flexDirection: 'row',
|
|
113
|
+
flexWrap: 'nowrap'
|
|
114
|
+
}
|
|
115
|
+
|
|
100
116
|
// 对角线角度
|
|
101
117
|
const diagonalAngleMap: Record<string, (width: number, height: number) => any> = {
|
|
102
118
|
'top right': (width: number, height: number) => {
|
|
@@ -122,24 +138,36 @@ function radToAngle (r: number) {
|
|
|
122
138
|
return r * 180 / Math.PI
|
|
123
139
|
}
|
|
124
140
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
141
|
+
// === linear-gradient 解析相关正则(模块级,一次创建) ===
|
|
142
|
+
// CSS <angle> 支持 deg/turn/rad/grad 四种单位,统一归一为 deg
|
|
143
|
+
// https://www.w3.org/TR/css-values-3/#angles
|
|
144
|
+
const angleRegExp = /^\s*(-?\d+(?:\.\d+)?)(deg|turn|rad|grad)\b/
|
|
145
|
+
const gradientToRegExp = /^to\b\s*/
|
|
146
|
+
// 入口形态:仅在含 linear-gradient 时走解析;提取括号内内容
|
|
147
|
+
const linearGradientRegExp = /linear-gradient\((.*)\)/
|
|
148
|
+
// 顶层逗号切分(忽略 () / # 内部的逗号)
|
|
149
|
+
const topLevelCommaRegExp = /,(?![^(#]*\))/
|
|
150
|
+
// 色标内空白切分(忽略色函数里的逗号边界)
|
|
151
|
+
const stopWhitespaceRegExp = /(?<!,)\s+/
|
|
152
|
+
// 色标位置仅支持 `<n>%` 或裸 `0`(CSS 允许 0 作为唯一无单位 length)
|
|
153
|
+
// 其它单位(px/rpx/em/vw/...)当前无法在不依赖 layout 的情况下归一为百分比,统一拒绝
|
|
154
|
+
const validStopPosRegExp = /^-?\d+(?:\.\d+)?%$|^0$/
|
|
155
|
+
// color hint 检测:色标 token 仅含一个分量且以数字/正负号/小数点开头
|
|
156
|
+
const colorHintLeadingRegExp = /^[-+.\d]/
|
|
157
|
+
|
|
158
|
+
function normalizeAngle (raw: string): number | undefined {
|
|
159
|
+
const m = raw.match(angleRegExp)
|
|
160
|
+
if (!m) return undefined
|
|
161
|
+
const n = +m[1]
|
|
162
|
+
switch (m[2]) {
|
|
163
|
+
case 'turn': return n * 360
|
|
164
|
+
case 'rad': return radToAngle(n)
|
|
165
|
+
case 'grad': return n * 0.9
|
|
166
|
+
default: return n // deg
|
|
128
167
|
}
|
|
129
168
|
}
|
|
130
169
|
|
|
131
|
-
const
|
|
132
|
-
['backgroundSize', 'backgroundPosition'].forEach(name => {
|
|
133
|
-
if (style[name] && typeof style[name] === 'string') {
|
|
134
|
-
if (style[name].trim()) {
|
|
135
|
-
style[name] = style[name].split(' ')
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
})
|
|
139
|
-
return style
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
const isPercent = (val: string | number | undefined): val is string => typeof val === 'string' && PERCENT_REGEX.test(val)
|
|
170
|
+
const isPercent = (val: string | number | undefined): val is string => typeof val === 'string' && percentRegExp.test(val)
|
|
143
171
|
|
|
144
172
|
const isBackgroundSizeKeyword = (val: string | number): boolean => typeof val === 'string' && /^cover|contain$/.test(val)
|
|
145
173
|
|
|
@@ -261,12 +289,12 @@ function backgroundSize (imageProps: ImageProps, preImageInfo: PreImageInfo, ima
|
|
|
261
289
|
// 枚举值
|
|
262
290
|
if (typeof width === 'string' && ['cover', 'contain'].includes(width)) {
|
|
263
291
|
if (layoutInfo && imageSize) {
|
|
264
|
-
const
|
|
265
|
-
const
|
|
266
|
-
// 容器宽高比
|
|
267
|
-
if ((
|
|
292
|
+
const containerRatio = layoutWidth / layoutHeight
|
|
293
|
+
const imageRatio = imageSizeWidth / imageSizeHeight
|
|
294
|
+
// 容器宽高比 小于等于 图片宽高比:contain 按宽缩放,cover 按高缩放
|
|
295
|
+
if ((containerRatio <= imageRatio && (width as string) === 'contain') || (containerRatio >= imageRatio && (width as string) === 'cover')) {
|
|
268
296
|
dimensions = calculateSize(layoutWidth as number, imageSizeHeight / imageSizeWidth, true) as Size
|
|
269
|
-
} else if ((
|
|
297
|
+
} else if ((containerRatio > imageRatio && (width as string) === 'contain') || (containerRatio < imageRatio && (width as string) === 'cover')) {
|
|
270
298
|
dimensions = calculateSize(layoutHeight as number, imageSizeWidth / imageSizeHeight) as Size
|
|
271
299
|
}
|
|
272
300
|
}
|
|
@@ -325,7 +353,16 @@ function linearGradient (imageProps: ImageProps, preImageInfo: PreImageInfo, ima
|
|
|
325
353
|
if (type !== 'linear') return
|
|
326
354
|
|
|
327
355
|
// 角度计算
|
|
328
|
-
|
|
356
|
+
// 注意:不要用 `linearMap.get(direction) || ...`,因为 'top' 映射为 0 是 falsy 值,
|
|
357
|
+
// 会被误判为未命中并落到默认 180deg
|
|
358
|
+
let angle: number
|
|
359
|
+
if (linearMap.has(direction)) {
|
|
360
|
+
angle = linearMap.get(direction) as number
|
|
361
|
+
} else {
|
|
362
|
+
const normalized = normalizeAngle(direction)
|
|
363
|
+
angle = normalized !== undefined ? normalized : 180
|
|
364
|
+
}
|
|
365
|
+
angle = angle % 360
|
|
329
366
|
|
|
330
367
|
// 对角线角度计算
|
|
331
368
|
if (layoutInfo && diagonalAngleMap[direction] && imageSize && linearInfo) {
|
|
@@ -339,16 +376,29 @@ function linearGradient (imageProps: ImageProps, preImageInfo: PreImageInfo, ima
|
|
|
339
376
|
}
|
|
340
377
|
|
|
341
378
|
const imageStyleToProps = (preImageInfo: PreImageInfo, imageSize: Size, layoutInfo: Size) => {
|
|
342
|
-
|
|
379
|
+
const { type } = preImageInfo
|
|
343
380
|
const imageProps: ImageProps = {
|
|
344
|
-
resizeMode: 'cover',
|
|
345
381
|
style: {
|
|
346
382
|
position: 'absolute'
|
|
347
383
|
// ...StyleSheet.absoluteFillObject
|
|
348
|
-
}
|
|
349
|
-
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
if (type === 'image') {
|
|
388
|
+
imageProps.resizeMode = 'cover'
|
|
389
|
+
} else {
|
|
390
|
+
imageProps.colors = []
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
backgroundSize(imageProps, preImageInfo, imageSize, layoutInfo)
|
|
394
|
+
if (preImageInfo.backgroundPosition.length) {
|
|
395
|
+
backgroundPosition(imageProps, preImageInfo, imageSize, layoutInfo)
|
|
396
|
+
}
|
|
397
|
+
if (type === 'image') {
|
|
398
|
+
backgroundImage(imageProps, preImageInfo)
|
|
399
|
+
} else {
|
|
400
|
+
linearGradient(imageProps, preImageInfo, imageSize, layoutInfo)
|
|
350
401
|
}
|
|
351
|
-
applyHandlers([backgroundSize, backgroundImage, backgroundPosition, linearGradient], [imageProps, preImageInfo, imageSize, layoutInfo])
|
|
352
402
|
|
|
353
403
|
return imageProps
|
|
354
404
|
}
|
|
@@ -456,23 +506,58 @@ function calcSteps (startVal: number, endVal: number, len: number) {
|
|
|
456
506
|
return newArr
|
|
457
507
|
}
|
|
458
508
|
|
|
459
|
-
|
|
460
|
-
|
|
509
|
+
// 返回值约定:
|
|
510
|
+
// - LinearInfo 解析成功
|
|
511
|
+
// - null 已识别为 linear-gradient 但内部已通过 error/warn 报错,外部不要再报
|
|
512
|
+
// - undefined 不是 linear-gradient 形态,外部按"不支持的 background-image"处理
|
|
513
|
+
function parseLinearGradient (text: string): LinearInfo | null | undefined {
|
|
514
|
+
let linearText = text.trim().match(linearGradientRegExp)?.[1]
|
|
461
515
|
if (!linearText) return
|
|
462
516
|
|
|
463
|
-
//
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
517
|
+
// 多重渐变 / 多重背景:linearGradientRegExp 用了贪婪 `.*`,多渐变时括号内
|
|
518
|
+
// 会贪到下一段 `linear-gradient(`,单段则一定不含;用 includes 一次判断即可
|
|
519
|
+
if (linearText.includes('linear-gradient(')) {
|
|
520
|
+
error(`[mpx-view] background-image 暂不支持多重渐变 (multi gradients),已丢弃,原值: ${text}`)
|
|
521
|
+
return null
|
|
468
522
|
}
|
|
469
523
|
|
|
470
524
|
// 把 0deg, red 10%, blue 20% 解析为 ['0deg', 'red, 10%', 'blue, 20%']
|
|
471
|
-
|
|
525
|
+
if (gradientToRegExp.test(linearText)) {
|
|
526
|
+
linearText = linearText.replace(gradientToRegExp, '')
|
|
527
|
+
} else if (!angleRegExp.test(linearText)) {
|
|
528
|
+
linearText = '180deg ,' + linearText
|
|
529
|
+
}
|
|
530
|
+
const [direction, ...colorList] = linearText.split(topLevelCommaRegExp)
|
|
472
531
|
// 记录需要填充起点的起始位置
|
|
473
532
|
let startIdx = 0; let startVal = 0
|
|
474
533
|
// 把 ['red, 10%', 'blue, 20%']解析为 [[red, 10%], [blue, 20%]]
|
|
475
|
-
|
|
534
|
+
// 双位置语法展开:['red', '0%', '50%'] → [['red', '0%'], ['red', '50%']]
|
|
535
|
+
// 等价于 CSS Images Level 4 中 `red 0% 50%` ≡ `red 0%, red 50%`
|
|
536
|
+
// 同步对不支持的写法做拦截:color hint(仅一个位置 token)、非百分比位置(px/rpx 等)
|
|
537
|
+
const linearInfo = colorList
|
|
538
|
+
.map(item => item.trim().split(stopWhitespaceRegExp))
|
|
539
|
+
.reduce<string[][]>((acc, parts) => {
|
|
540
|
+
// color hint: 例如 `linear-gradient(red, 30%, blue)` 中的 `30%`
|
|
541
|
+
// 该 token 仅含一个位置值、无颜色;当前实现无法做颜色采样,直接丢弃
|
|
542
|
+
if (parts.length === 1 && colorHintLeadingRegExp.test(parts[0])) {
|
|
543
|
+
warn(`[mpx-view] linear-gradient 暂不支持 color hint 写法 [${parts[0]}],已丢弃该色标`)
|
|
544
|
+
return acc
|
|
545
|
+
}
|
|
546
|
+
const [color, ...positions] = parts
|
|
547
|
+
if (positions.length === 0) {
|
|
548
|
+
acc.push([color])
|
|
549
|
+
} else {
|
|
550
|
+
for (const pos of positions) {
|
|
551
|
+
if (!validStopPosRegExp.test(pos)) {
|
|
552
|
+
warn(`[mpx-view] linear-gradient 色标位置仅支持百分比 [${color} ${pos}] 已丢弃位置,仅保留颜色`)
|
|
553
|
+
acc.push([color])
|
|
554
|
+
} else {
|
|
555
|
+
acc.push([color, pos])
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
return acc
|
|
560
|
+
}, [])
|
|
476
561
|
.reduce<LinearInfo>((prev, cur, idx, self) => {
|
|
477
562
|
const { colors, locations } = prev
|
|
478
563
|
const [color, val] = cur
|
|
@@ -502,12 +587,18 @@ function parseLinearGradient (text: string): LinearInfo | undefined {
|
|
|
502
587
|
return prev
|
|
503
588
|
}, { colors: [], locations: [] })
|
|
504
589
|
|
|
590
|
+
// 色标全部被丢弃或不足以构成渐变(至少 2 个颜色),降级返回
|
|
591
|
+
if (linearInfo.colors.length < 2) {
|
|
592
|
+
error(`[mpx-view] linear-gradient 至少需要 2 个有效色标,已丢弃,原值: ${text}`)
|
|
593
|
+
return null
|
|
594
|
+
}
|
|
595
|
+
|
|
505
596
|
return extendObject({}, linearInfo, {
|
|
506
597
|
direction: direction.trim()
|
|
507
598
|
})
|
|
508
599
|
}
|
|
509
600
|
|
|
510
|
-
function parseBgImage (text
|
|
601
|
+
function parseBgImage (text?: string): {
|
|
511
602
|
linearInfo?: LinearInfo
|
|
512
603
|
direction?: string
|
|
513
604
|
type?: 'image' | 'linear'
|
|
@@ -519,13 +610,21 @@ function parseBgImage (text: string): {
|
|
|
519
610
|
if (src) return { src, type: 'image' }
|
|
520
611
|
|
|
521
612
|
const linearInfo = parseLinearGradient(text)
|
|
522
|
-
if (!linearInfo)
|
|
613
|
+
if (!linearInfo) {
|
|
614
|
+
// null 表示 parseLinearGradient 内部已报错,外部不要重复;undefined 才属于未识别形态
|
|
615
|
+
if (linearInfo === undefined) {
|
|
616
|
+
error(`[mpx-view] background-image 暂不支持 ${text},已丢弃,仅支持 url(...) / linear-gradient(...)。`)
|
|
617
|
+
}
|
|
618
|
+
return {}
|
|
619
|
+
}
|
|
523
620
|
return {
|
|
524
621
|
linearInfo,
|
|
525
622
|
type: 'linear'
|
|
526
623
|
}
|
|
527
624
|
}
|
|
528
625
|
|
|
626
|
+
export const __parseBgImageForTest = (text?: string): any => parseBgImage(text)
|
|
627
|
+
|
|
529
628
|
function normalizeBackgroundSize (
|
|
530
629
|
backgroundSize: NonNullable<ExtendedViewStyle['backgroundSize']>,
|
|
531
630
|
type: 'image' | 'linear' | undefined
|
|
@@ -546,19 +645,6 @@ function normalizeBackgroundSize (
|
|
|
546
645
|
})
|
|
547
646
|
}
|
|
548
647
|
|
|
549
|
-
function preParseImage (imageStyle?: ExtendedViewStyle) {
|
|
550
|
-
const { backgroundImage = '', backgroundSize = ['auto'], backgroundPosition = [0, 0] } = normalizeStyle(imageStyle) || {}
|
|
551
|
-
const { type, src, linearInfo } = parseBgImage(backgroundImage)
|
|
552
|
-
|
|
553
|
-
return {
|
|
554
|
-
src,
|
|
555
|
-
linearInfo,
|
|
556
|
-
type,
|
|
557
|
-
sizeList: normalizeBackgroundSize(backgroundSize, type),
|
|
558
|
-
backgroundPosition: normalizeBackgroundPosition(backgroundPosition)
|
|
559
|
-
}
|
|
560
|
-
}
|
|
561
|
-
|
|
562
648
|
function isDiagonalAngle (linearInfo?: LinearInfo): boolean {
|
|
563
649
|
return !!(linearInfo?.direction && diagonalAngleMap[linearInfo.direction])
|
|
564
650
|
}
|
|
@@ -583,21 +669,48 @@ function inheritStyle (innerStyle: ExtendedViewStyle = {}) {
|
|
|
583
669
|
}
|
|
584
670
|
|
|
585
671
|
function useWrapImage (imageStyle?: ExtendedViewStyle, innerStyle?: Record<string, any>, enableFastImage?: boolean) {
|
|
586
|
-
|
|
587
|
-
const
|
|
588
|
-
|
|
589
|
-
const
|
|
672
|
+
const backgroundImage = imageStyle?.backgroundImage
|
|
673
|
+
const backgroundSize = imageStyle?.backgroundSize
|
|
674
|
+
const backgroundPosition = imageStyle?.backgroundPosition
|
|
675
|
+
const parsedImageInfo = useMemo(() => parseBgImage(backgroundImage), [backgroundImage])
|
|
676
|
+
const { src, type } = parsedImageInfo
|
|
677
|
+
const backgroundSizeKey = Array.isArray(backgroundSize) ? backgroundSize.join('|') : backgroundSize
|
|
678
|
+
const sizeList = useMemo(
|
|
679
|
+
() => normalizeBackgroundSize(backgroundSize ?? ['auto'], type),
|
|
680
|
+
[backgroundSizeKey, type]
|
|
681
|
+
)
|
|
682
|
+
const backgroundPositionKey = Array.isArray(backgroundPosition) ? backgroundPosition.join('|') : backgroundPosition
|
|
683
|
+
const bgPosition = useMemo(
|
|
684
|
+
() => normalizeBackgroundPosition(backgroundPosition ?? [0, 0]),
|
|
685
|
+
[backgroundPositionKey]
|
|
686
|
+
)
|
|
687
|
+
const preImageInfo: PreImageInfo = useMemo(
|
|
688
|
+
() => extendObject({}, parsedImageInfo, { sizeList, backgroundPosition: bgPosition }),
|
|
689
|
+
[parsedImageInfo, sizeList, bgPosition]
|
|
690
|
+
)
|
|
590
691
|
|
|
591
692
|
// 判断是否可挂载onLayout
|
|
592
693
|
const { needLayout, needImageSize } = checkNeedLayout(preImageInfo)
|
|
593
694
|
|
|
594
695
|
const [show, setShow] = useState<boolean>(((type === 'image' && !!src) || type === 'linear') && !needLayout && !needImageSize)
|
|
595
|
-
const [,
|
|
596
|
-
const [, setImageSizeHeight] = useState<number | null>(null)
|
|
597
|
-
const [, setLayoutInfoWidth] = useState<number | null>(null)
|
|
598
|
-
const [, setLayoutInfoHeight] = useState<number | null>(null)
|
|
696
|
+
const [version, setVersion] = useState(0)
|
|
599
697
|
const sizeInfo = useRef<Size | null>(null)
|
|
600
698
|
const layoutInfo = useRef<Size | null>(null)
|
|
699
|
+
const sizeCacheRef = useRef<Map<string, Size>>(new Map())
|
|
700
|
+
// sizeInfo / layoutInfo / setVersion 都是稳定引用,闭包整个生命周期只分配一次
|
|
701
|
+
const { bumpVersion, setImageSize, setLayoutInfo } = useMemo(() => ({
|
|
702
|
+
bumpVersion: () => setVersion(version => version + 1),
|
|
703
|
+
setImageSize: (width: number, height: number) => {
|
|
704
|
+
if (sizeInfo.current?.width === width && sizeInfo.current?.height === height) return false
|
|
705
|
+
sizeInfo.current = { width, height }
|
|
706
|
+
return true
|
|
707
|
+
},
|
|
708
|
+
setLayoutInfo: (width: number, height: number) => {
|
|
709
|
+
if (layoutInfo.current?.width === width && layoutInfo.current?.height === height) return false
|
|
710
|
+
layoutInfo.current = { width, height }
|
|
711
|
+
return true
|
|
712
|
+
}
|
|
713
|
+
}), [])
|
|
601
714
|
useEffect(() => {
|
|
602
715
|
sizeInfo.current = null
|
|
603
716
|
if (type === 'linear') {
|
|
@@ -615,54 +728,55 @@ function useWrapImage (imageStyle?: ExtendedViewStyle, innerStyle?: Record<strin
|
|
|
615
728
|
}
|
|
616
729
|
|
|
617
730
|
if (needImageSize) {
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
731
|
+
const cached = sizeCacheRef.current.get(src)
|
|
732
|
+
if (cached) {
|
|
733
|
+
const imageSizeChanged = setImageSize(cached.width, cached.height)
|
|
734
|
+
if (!needLayout || layoutInfo.current) {
|
|
735
|
+
imageSizeChanged && bumpVersion()
|
|
736
|
+
setShow(true)
|
|
622
737
|
}
|
|
738
|
+
return
|
|
739
|
+
}
|
|
740
|
+
let cancelled = false
|
|
741
|
+
Image.getSize(src, (width, height) => {
|
|
742
|
+
// cache 仍然填上,避免下次同 src 再发一次请求
|
|
743
|
+
sizeCacheRef.current.set(src, { width, height })
|
|
744
|
+
if (cancelled) return
|
|
745
|
+
const imageSizeChanged = setImageSize(width, height)
|
|
623
746
|
// 1. 当需要绑定onLayout 2. 获取到布局信息
|
|
624
747
|
if (!needLayout || layoutInfo.current) {
|
|
625
|
-
|
|
626
|
-
setImageSizeHeight(height)
|
|
627
|
-
if (layoutInfo.current) {
|
|
628
|
-
setLayoutInfoWidth(layoutInfo.current.width)
|
|
629
|
-
setLayoutInfoHeight(layoutInfo.current.height)
|
|
630
|
-
}
|
|
748
|
+
imageSizeChanged && bumpVersion()
|
|
631
749
|
setShow(true)
|
|
632
750
|
}
|
|
633
751
|
})
|
|
752
|
+
return () => { cancelled = true }
|
|
634
753
|
}
|
|
635
754
|
// type 添加type 处理无渐变 有渐变的场景
|
|
636
|
-
}, [src, type])
|
|
755
|
+
}, [src, type, needLayout, needImageSize])
|
|
756
|
+
|
|
757
|
+
const imageProps = useMemo(
|
|
758
|
+
() => imageStyleToProps(preImageInfo, sizeInfo.current as Size, layoutInfo.current as Size),
|
|
759
|
+
[preImageInfo, version]
|
|
760
|
+
)
|
|
637
761
|
|
|
638
762
|
if (!type) return null
|
|
639
763
|
|
|
640
764
|
const onLayout = (res: LayoutChangeEvent) => {
|
|
641
765
|
const { width, height } = res?.nativeEvent?.layout || {}
|
|
642
|
-
layoutInfo.current
|
|
643
|
-
|
|
644
|
-
height
|
|
645
|
-
}
|
|
766
|
+
// layoutInfo 总是更新,Image.getSize 回调要靠 layoutInfo.current 决定是否 setShow
|
|
767
|
+
let changed = setLayoutInfo(width, height)
|
|
646
768
|
if (!needImageSize) {
|
|
647
|
-
setLayoutInfoWidth(width)
|
|
648
|
-
setLayoutInfoHeight(height)
|
|
649
769
|
// 有渐变角度的时候,才触发渲染组件
|
|
650
770
|
if (type === 'linear') {
|
|
651
|
-
|
|
652
|
-
width: calcPercent(sizeList[0] as NumberVal, width),
|
|
653
|
-
height: calcPercent(sizeList[1] as NumberVal, height)
|
|
654
|
-
}
|
|
655
|
-
setImageSizeWidth(sizeInfo.current.width)
|
|
656
|
-
setImageSizeHeight(sizeInfo.current.height)
|
|
771
|
+
changed = setImageSize(calcPercent(sizeList[0] as NumberVal, width), calcPercent(sizeList[1] as NumberVal, height)) || changed
|
|
657
772
|
}
|
|
773
|
+
changed && bumpVersion()
|
|
658
774
|
setShow(true)
|
|
659
775
|
} else if (sizeInfo.current) {
|
|
660
|
-
|
|
661
|
-
setLayoutInfoHeight(height)
|
|
662
|
-
setImageSizeWidth(sizeInfo.current.width)
|
|
663
|
-
setImageSizeHeight(sizeInfo.current.height)
|
|
776
|
+
changed && bumpVersion()
|
|
664
777
|
setShow(true)
|
|
665
778
|
}
|
|
779
|
+
// needImageSize && !sizeInfo.current:等 Image.getSize 回调里 setShow(true),此处不触发渲染
|
|
666
780
|
}
|
|
667
781
|
|
|
668
782
|
const backgroundProps: ViewProps = extendObject({ key: 'backgroundImage' }, needLayout ? { onLayout } : {},
|
|
@@ -670,45 +784,45 @@ function useWrapImage (imageStyle?: ExtendedViewStyle, innerStyle?: Record<strin
|
|
|
670
784
|
)
|
|
671
785
|
|
|
672
786
|
return createElement(View, backgroundProps,
|
|
673
|
-
show && type === 'linear' && createElement(LinearGradient, extendObject({ useAngle: true },
|
|
674
|
-
show && type === 'image' && renderImage(
|
|
787
|
+
show && type === 'linear' && createElement(LinearGradient, extendObject({ useAngle: true }, imageProps as LinearImageProps)),
|
|
788
|
+
show && type === 'image' && renderImage(imageProps, enableFastImage)
|
|
675
789
|
)
|
|
676
790
|
}
|
|
677
791
|
|
|
678
792
|
interface WrapChildrenConfig {
|
|
679
793
|
hasVarDec: boolean
|
|
680
794
|
enableBackground?: boolean
|
|
681
|
-
textStyle?: TextStyle
|
|
682
795
|
backgroundStyle?: ExtendedViewStyle
|
|
683
796
|
varContext?: Record<string, any>
|
|
684
|
-
|
|
685
|
-
textPassThrough?: ReturnType<typeof useTextPassThroughValue>
|
|
797
|
+
textPassThrough?: TextPassThroughContextValue | null
|
|
686
798
|
innerStyle?: Record<string, any>
|
|
687
799
|
enableFastImage?: boolean
|
|
688
800
|
}
|
|
689
801
|
|
|
690
802
|
function wrapWithChildren (props: _ViewProps, { hasVarDec, enableBackground, backgroundStyle, varContext, textPassThrough, innerStyle, enableFastImage }: WrapChildrenConfig) {
|
|
691
|
-
const children = wrapChildren(props, {
|
|
803
|
+
const children = wrapChildren(props.children, {
|
|
692
804
|
hasVarDec,
|
|
693
805
|
varContext,
|
|
694
806
|
textPassThrough
|
|
695
807
|
})
|
|
696
808
|
|
|
809
|
+
if (!enableBackground) return children
|
|
810
|
+
|
|
697
811
|
return [
|
|
698
812
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
699
|
-
|
|
813
|
+
useWrapImage(backgroundStyle, innerStyle, enableFastImage),
|
|
700
814
|
children
|
|
701
815
|
]
|
|
702
816
|
}
|
|
703
817
|
|
|
704
818
|
const _View = forwardRef<HandlerRef<View, _ViewProps>, _ViewProps>((viewProps, ref): JSX.Element => {
|
|
705
819
|
// 性能探针 - total
|
|
706
|
-
let
|
|
707
|
-
if (__mpx_perf_framework__)
|
|
820
|
+
let idTotal = -1
|
|
821
|
+
if (__mpx_perf_framework__) idTotal = perf.scopeStart('view:render:total')
|
|
708
822
|
|
|
709
823
|
// ───── props 阶段 ─────
|
|
710
|
-
let
|
|
711
|
-
if (__mpx_perf_framework__)
|
|
824
|
+
let idProps = -1
|
|
825
|
+
if (__mpx_perf_framework__) idProps = perf.scopeStart('view:render:props')
|
|
712
826
|
const { textProps, innerProps: props = {} } = splitProps(viewProps)
|
|
713
827
|
let {
|
|
714
828
|
style = {},
|
|
@@ -716,8 +830,8 @@ const _View = forwardRef<HandlerRef<View, _ViewProps>, _ViewProps>((viewProps, r
|
|
|
716
830
|
'hover-start-time': hoverStartTime = 50,
|
|
717
831
|
'hover-stay-time': hoverStayTime = 400,
|
|
718
832
|
'enable-var': enableVar,
|
|
719
|
-
'external-var-context': externalVarContext,
|
|
720
833
|
'enable-background': enableBackground,
|
|
834
|
+
'enable-text-pass-through': enableTextPassThrough,
|
|
721
835
|
'enable-fast-image': enableFastImage,
|
|
722
836
|
'enable-animation': enableAnimation,
|
|
723
837
|
'parent-font-size': parentFontSize,
|
|
@@ -728,25 +842,17 @@ const _View = forwardRef<HandlerRef<View, _ViewProps>, _ViewProps>((viewProps, r
|
|
|
728
842
|
bindtransitionend
|
|
729
843
|
} = props
|
|
730
844
|
|
|
731
|
-
// 默认样式
|
|
732
|
-
const defaultStyle: ExtendedViewStyle = style.display === 'flex'
|
|
733
|
-
? {
|
|
734
|
-
flexDirection: 'row',
|
|
735
|
-
flexBasis: 'auto',
|
|
736
|
-
flexShrink: 1,
|
|
737
|
-
flexWrap: 'nowrap'
|
|
738
|
-
}
|
|
739
|
-
: {}
|
|
740
|
-
|
|
741
845
|
const enableHover = !!hoverStyle
|
|
742
846
|
const { isHover, gesture } = useHover({ enableHover, hoverStartTime, hoverStayTime })
|
|
743
847
|
|
|
744
|
-
const styleObj: ExtendedViewStyle =
|
|
745
|
-
|
|
848
|
+
const styleObj: ExtendedViewStyle = isHover
|
|
849
|
+
? extendObject({}, style, hoverStyle as ExtendedViewStyle)
|
|
850
|
+
: style
|
|
851
|
+
if (__mpx_perf_framework__) perf.scopeEnd(idProps)
|
|
746
852
|
|
|
747
853
|
// ───── style 阶段 ─────
|
|
748
|
-
let
|
|
749
|
-
if (__mpx_perf_framework__)
|
|
854
|
+
let idStyle = -1
|
|
855
|
+
if (__mpx_perf_framework__) idStyle = perf.scopeStart('view:render:style')
|
|
750
856
|
const {
|
|
751
857
|
normalStyle,
|
|
752
858
|
hasSelfPercent,
|
|
@@ -757,14 +863,18 @@ const _View = forwardRef<HandlerRef<View, _ViewProps>, _ViewProps>((viewProps, r
|
|
|
757
863
|
setHeight
|
|
758
864
|
} = useTransformStyle(styleObj, {
|
|
759
865
|
enableVar,
|
|
760
|
-
externalVarContext,
|
|
761
866
|
parentFontSize,
|
|
762
867
|
parentWidth,
|
|
763
|
-
parentHeight
|
|
868
|
+
parentHeight,
|
|
869
|
+
// 基于合并后的 styleObj 判断(hover 状态切换 display 也能触发)
|
|
870
|
+
// 用户传 flex shorthand 时使用精简 default,避免 flexBasis/flexShrink 反向覆盖
|
|
871
|
+
defaultStyle: styleObj.display === 'flex'
|
|
872
|
+
? (hasOwn(styleObj, 'flex') ? FLEX_DEFAULT_STYLE_TRIMMED : FLEX_DEFAULT_STYLE)
|
|
873
|
+
: undefined
|
|
764
874
|
})
|
|
765
875
|
|
|
766
876
|
const { textStyle, backgroundStyle, innerStyle = {} } = splitStyle(normalStyle)
|
|
767
|
-
const textPassThrough =
|
|
877
|
+
const textPassThrough = useTextPassThrough(textStyle, textProps, { enableTextPassThrough })
|
|
768
878
|
|
|
769
879
|
enableBackground = enableBackground || !!backgroundStyle
|
|
770
880
|
const enableBackgroundRef = useRef(enableBackground)
|
|
@@ -783,24 +893,22 @@ const _View = forwardRef<HandlerRef<View, _ViewProps>, _ViewProps>((viewProps, r
|
|
|
783
893
|
layoutProps
|
|
784
894
|
} = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef })
|
|
785
895
|
|
|
786
|
-
const viewStyle =
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
: isFunction(bindtransitionend)
|
|
790
|
-
? bindtransitionend
|
|
791
|
-
: undefined
|
|
896
|
+
const viewStyle = layoutStyle
|
|
897
|
+
? extendObject({}, innerStyle, layoutStyle)
|
|
898
|
+
: innerStyle
|
|
792
899
|
const { enableStyleAnimation, animationStyle } = useAnimationHooks({
|
|
793
900
|
layoutRef,
|
|
794
901
|
animation,
|
|
795
902
|
enableAnimation,
|
|
796
903
|
style: viewStyle,
|
|
797
|
-
|
|
904
|
+
catchtransitionend,
|
|
905
|
+
bindtransitionend
|
|
798
906
|
})
|
|
799
|
-
if (__mpx_perf_framework__)
|
|
907
|
+
if (__mpx_perf_framework__) perf.scopeEnd(idStyle)
|
|
800
908
|
|
|
801
909
|
// ───── innerProps 阶段 ─────
|
|
802
|
-
let
|
|
803
|
-
if (__mpx_perf_framework__)
|
|
910
|
+
let idInnerProps = -1
|
|
911
|
+
if (__mpx_perf_framework__) idInnerProps = perf.scopeStart('view:render:innerProps')
|
|
804
912
|
const innerProps = useInnerProps(
|
|
805
913
|
extendObject(
|
|
806
914
|
{},
|
|
@@ -812,25 +920,26 @@ const _View = forwardRef<HandlerRef<View, _ViewProps>, _ViewProps>((viewProps, r
|
|
|
812
920
|
}
|
|
813
921
|
),
|
|
814
922
|
[
|
|
815
|
-
'animation',
|
|
816
923
|
'hover-start-time',
|
|
817
924
|
'hover-stay-time',
|
|
818
925
|
'hover-style',
|
|
819
926
|
'hover-class',
|
|
820
|
-
'enable-
|
|
927
|
+
'enable-background',
|
|
821
928
|
'enable-animation',
|
|
822
|
-
'
|
|
823
|
-
'
|
|
929
|
+
'enable-fast-image',
|
|
930
|
+
'animation',
|
|
931
|
+
'catchtransitionend',
|
|
932
|
+
'bindtransitionend'
|
|
824
933
|
],
|
|
825
934
|
{
|
|
826
935
|
layoutRef
|
|
827
936
|
}
|
|
828
937
|
)
|
|
829
|
-
if (__mpx_perf_framework__)
|
|
938
|
+
if (__mpx_perf_framework__) perf.scopeEnd(idInnerProps)
|
|
830
939
|
|
|
831
940
|
// ───── createElement 阶段 ─────
|
|
832
|
-
let
|
|
833
|
-
if (__mpx_perf_framework__)
|
|
941
|
+
let idCreate = -1
|
|
942
|
+
if (__mpx_perf_framework__) idCreate = perf.scopeStart('view:render:createElement')
|
|
834
943
|
const childNode = wrapWithChildren(props, {
|
|
835
944
|
hasVarDec,
|
|
836
945
|
enableBackground: enableBackgroundRef.current,
|
|
@@ -852,9 +961,9 @@ const _View = forwardRef<HandlerRef<View, _ViewProps>, _ViewProps>((viewProps, r
|
|
|
852
961
|
if (hasPositionFixed) {
|
|
853
962
|
finalComponent = createElement(Portal, null, finalComponent)
|
|
854
963
|
}
|
|
855
|
-
if (__mpx_perf_framework__)
|
|
964
|
+
if (__mpx_perf_framework__) perf.scopeEnd(idCreate)
|
|
856
965
|
|
|
857
|
-
if (__mpx_perf_framework__)
|
|
966
|
+
if (__mpx_perf_framework__) perf.scopeEnd(idTotal)
|
|
858
967
|
return finalComponent
|
|
859
968
|
})
|
|
860
969
|
|