From bbcbee740adef394d60fd7bab1a5d339af4673ce Mon Sep 17 00:00:00 2001 From: shangqunfeng Date: Thu, 23 May 2024 12:00:57 +0800 Subject: [PATCH 01/45] fix(*): fix style. --- .../lib/runtime/components/react/mpx-view.tsx | 146 +++++++++--------- .../lib/runtime/components/react/utils.ts | 2 +- 2 files changed, 71 insertions(+), 77 deletions(-) diff --git a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx index d6e0233637..0720ab036d 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx +++ b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx @@ -12,24 +12,23 @@ import useInnerTouchable from './getInnerListeners' // @ts-ignore import useNodesRef from '../../useNodesRef' // 引入辅助函数 -import { extractTextStlye, parseUrl, hasElementType } from './utils' +import { parseUrl, hasElementType, TEXT_STYLE_REGEX } from './utils' type ExtendedViewStyle = ViewStyle & { backgroundImage?: string backgroundSize?: ImageResizeMode } -export interface _ViewProps extends ExtendedViewStyle { - style?: Array; - children?: React.ReactElement; - hoverStyle: Array; - bindtouchstart?: (event: NativeSyntheticEvent | unknown) => void; - bindtouchmove?: (event: NativeSyntheticEvent | unknown) => void; - bindtouchend?: (event: NativeSyntheticEvent | unknown) => void; -} - +type ElementNode = Exclude -const bgSizeList = ['cover', 'contain', 'stretch'] +export interface _ViewProps extends ViewProps { + style?: Array + children?: ElementNode + hoverStyle: Array + bindtouchstart?: (event: NativeSyntheticEvent | unknown) => void + bindtouchmove?: (event: NativeSyntheticEvent | unknown) => void + bindtouchend?: (event: NativeSyntheticEvent | unknown) => void +} const DEFAULT_STYLE = { flexDirection: 'row', @@ -40,80 +39,78 @@ function getDefaultStyle(style: ViewStyle = {}) { return style.display === 'flex' ? DEFAULT_STYLE : {} } -function getMergeStyle(style: Array = []):ExtendedViewStyle { - const mergedStyle: ExtendedViewStyle = Object.assign({}, ...style) +function getMergeStyle(style: Array = [], hoverStyle: Array = []):ExtendedViewStyle { + const mergedStyle: ExtendedViewStyle = Object.assign({}, ...style, ...hoverStyle) return { ...getDefaultStyle(mergedStyle), ...mergedStyle } } -const hasTextChild = (children: React.ReactElement) => { - let hasText = true - - React.Children.forEach(children, (child) => { - if (!hasElementType(child, 'mpx-text') && !hasElementType(child, 'Text')) { - hasText = false +function splitStyle(style: ExtendedViewStyle) { + let textStyle = null + let bjImage = null + let innerStyle = {} + + for (let key in style) { + let val = style[key] + if (TEXT_STYLE_REGEX.test(key)) { + textStyle = textStyle ?? {} + textStyle[key] = val + }else if (['backgroundImage', 'backgroundSize'].includes(key)) { + bjImage = bjImage ?? { + resizeMode: 'stretch' + } + if (key === 'backgroundSize') { + bjImage['resizeMode'] = ['cover', 'contain', 'stretch'].includes(val) ? val : 'stretch' + continue + } else if (key === 'backgroundImage'){ + bjImage['source'] = {uri: parseUrl(val)} + continue + } + } else { + innerStyle[key] = val } - }) + } + + return [ + textStyle, + bjImage, + innerStyle, + ] +} - return hasText +const isText = (children: ElementNode) => { + return hasElementType(children, 'mpx-text') || hasElementType(children, 'Text') } +function every(children: ElementNode, callback: (children: ElementNode) => boolean ) { + let hasSameElement = true -const cloneElement = (child: React.ReactElement, textStyle:ViewStyle = {}) => { - const {style, ...otherProps} = child.props || {} - return React.cloneElement(child, { - ...otherProps, - style: [textStyle, style] + React.Children.forEach(children, (child) => { + if (!callback(child)) { + hasSameElement = false + } }) + + return hasSameElement } -const elementInheritChildren = (children: React.ReactElement, style:ViewStyle = {}) => { - let textStyle = null - if (hasElementType(children, 'mpx-text')) { - textStyle = extractTextStlye(style) - return cloneElement(children, textStyle) - }else if (hasElementType(children, 'Text')) { - return cloneElement(children, textStyle) +const wrapChildren = (children: ElementNode, textStyle, bgImage, innerStyle) => { + if (every(children, (child)=>isText(child))) { + children = {children} } else { - return children + if(textStyle) console.warn('Text style will be ignored unless every child of the view is Text node!') } -} - -const wrapTextChildren = (children: React.ReactElement, style:ViewStyle = {}) => { - let textStyle = null - - const hasText = hasTextChild(children) - if (hasText) { - textStyle = extractTextStlye(style) - } - - return hasText ? { children } : children -} -const processChildren = (children: React.ReactElement, style:ViewStyle = {}) => { - return !Array.isArray(children) ? elementInheritChildren(children, style) : - wrapTextChildren(children, style) -} - - -const processBackgroundChildren = (children: React.ReactElement, style:ExtendedViewStyle = {}, image) => { - let resizeMode:ImageResizeMode = 'stretch' - if (bgSizeList.includes(style.backgroundSize)) { - resizeMode = style.backgroundSize + if(bgImage){ + children = {children} } - // 直接替换view,点击会时不时的不生效 - return - { processChildren(children, style) } - + return children } -const wrapChildren = (children, style, image) => { - return image ? processBackgroundChildren(children, style, image) : processChildren(children, style) -} const _View:React.FC<_ViewProps & React.RefAttributes> = React.forwardRef((props: _ViewProps, ref: React.ForwardedRef) => { const { @@ -123,7 +120,7 @@ const _View:React.FC<_ViewProps & React.RefAttributes> = React.forwardRef(( ...otherProps } = props const [isHover, setIsHover] = React.useState(false) - const finalStyle:ExtendedViewStyle = getMergeStyle(style) + const finalStyle:ExtendedViewStyle = getMergeStyle(style, isHover ? hoverStyle : []) const dataRef = React.useRef<{ startTimestamp: number, @@ -187,17 +184,15 @@ const _View:React.FC<_ViewProps & React.RefAttributes> = React.forwardRef(( defaultStyle: getDefaultStyle(finalStyle) }) - const image = parseUrl(finalStyle.backgroundImage) - - return ( - - {wrapChildren(children, finalStyle, image)} - - ) + const [textStyle, bgImage, innerStyle] = splitStyle(finalStyle) + + return ( + {wrapChildren(children, textStyle, bgImage, innerStyle)} + ) }) _View.displayName = 'mpx-view' @@ -205,4 +200,3 @@ _View.displayName = 'mpx-view' export default _View - diff --git a/packages/webpack-plugin/lib/runtime/components/react/utils.ts b/packages/webpack-plugin/lib/runtime/components/react/utils.ts index 65313c9a54..20d93bbfe0 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/utils.ts +++ b/packages/webpack-plugin/lib/runtime/components/react/utils.ts @@ -1,7 +1,7 @@ import { useEffect, useRef, Children, ReactElement, FunctionComponent } from 'react' import { StyleProp, StyleSheet, TextStyle, ViewStyle } from 'react-native' -const TEXT_STYLE_REGEX = /color|font.*|text.*|letterSpacing|lineHeight|includeFontPadding|writingDirection/ +export const TEXT_STYLE_REGEX = /color|font.*|text.*|letterSpacing|lineHeight|includeFontPadding|writingDirection/ const URL_REGEX = /url\(["']?(.*?)["']?\)/ export function omit(obj: T, fields: K[]): Omit { From 622042aab66232583eab9499eedfa0e465774f42 Mon Sep 17 00:00:00 2001 From: shangqunfeng Date: Thu, 23 May 2024 15:38:23 +0800 Subject: [PATCH 02/45] fix(*): fix code --- .../webpack-plugin/lib/runtime/components/react/mpx-view.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx index 0720ab036d..fa596e8031 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx +++ b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx @@ -62,11 +62,9 @@ function splitStyle(style: ExtendedViewStyle) { resizeMode: 'stretch' } if (key === 'backgroundSize') { - bjImage['resizeMode'] = ['cover', 'contain', 'stretch'].includes(val) ? val : 'stretch' - continue + bjImage['resizeMode'] = val } else if (key === 'backgroundImage'){ bjImage['source'] = {uri: parseUrl(val)} - continue } } else { innerStyle[key] = val From c031efc2e5f2e1447d70333ec7988278f67deb1d Mon Sep 17 00:00:00 2001 From: shangqunfeng Date: Thu, 23 May 2024 19:47:59 +0800 Subject: [PATCH 03/45] fix(*): fix code --- .../lib/runtime/components/react/mpx-view.tsx | 56 ------------------- 1 file changed, 56 deletions(-) diff --git a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx index c35d5ef067..5b7315dddc 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx +++ b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx @@ -38,62 +38,8 @@ export interface _ViewProps extends ExtendedViewStyle { bindtouchend?: (event: NativeSyntheticEvent | unknown) => void } -// function splitStyle(style: ExtendedViewStyle) { -// let textStyle = null -// let bjImage = null -// let innerStyle = {} - -// for (let key in style) { -// let val = style[key] -// if (TEXT_STYLE_REGEX.test(key)) { -// textStyle = textStyle ?? {} -// textStyle[key] = val -// }else if (['backgroundImage', 'backgroundSize'].includes(key)) { -// bjImage = bjImage ?? { -// resizeMode: 'stretch' -// } -// if (key === 'backgroundSize') { -// bjImage['resizeMode'] = val -// } else if (key === 'backgroundImage'){ -// bjImage['source'] = {uri: parseUrl(val)} -// } -// } else { -// innerStyle[key] = val -// } -// } - -// return [ -// textStyle, -// bjImage, -// innerStyle, -// ] -// } - -// const splitStyle = (style, testExps) => { -// const originStyle = { -// ...style -// } -// const splitStyleArr = [] -// Object.keys(StyleSheet.flatten(style)).forEach(prop => { -// testExps.forEach((exp, idx) => { -// if (exp.test(prop)) { -// if (splitStyleArr[idx]) { -// splitStyleArr[idx][prop] = style[prop] -// } else { -// splitStyleArr[idx] = { [prop]: style[prop] } -// } -// delete originStyle[prop] -// } -// }) -// }) -// splitStyleArr.push(originStyle) -// return splitStyleArr -// } - - type Obj = Record - function groupBy(style:Obj, callback: (key: string, val: string) => string ) { let group:Obj = {} for (let key in style) { @@ -107,8 +53,6 @@ function groupBy(style:Obj, callback: (key: string, val: string) => string ) { return group } - - const imageStyleToProps = (imageStyle: ExtendedViewStyle) => { if (!imageStyle) return null let bgImage:ImageProps = { From cd10a1078b36956683718496c1172eb4ff3867c6 Mon Sep 17 00:00:00 2001 From: shangqunfeng Date: Thu, 23 May 2024 20:22:40 +0800 Subject: [PATCH 04/45] fix(*): fix code --- .../lib/runtime/components/react/mpx-view.tsx | 31 ++++++++++++------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx index 5b7315dddc..3267168e5c 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx +++ b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx @@ -38,10 +38,12 @@ export interface _ViewProps extends ExtendedViewStyle { bindtouchend?: (event: NativeSyntheticEvent | unknown) => void } -type Obj = Record +type GroupData = { + [key: string]: ExtendedViewStyle +} -function groupBy(style:Obj, callback: (key: string, val: string) => string ) { - let group:Obj = {} +function groupBy(style:ExtendedViewStyle, callback: (key: string, val: string) => string ) { + let group:GroupData = {} for (let key in style) { let val = style[key] let groupKey = callback(key, val) @@ -54,7 +56,7 @@ function groupBy(style:Obj, callback: (key: string, val: string) => string ) { } const imageStyleToProps = (imageStyle: ExtendedViewStyle) => { - if (!imageStyle) return null + if (!imageStyle) return null let bgImage:ImageProps = { resizeMode: 'stretch' } @@ -102,6 +104,18 @@ function every(children: ElementNode, callback: (children: ElementNode) => boole return hasSameElement } +function wrapChildren(children: ElementNode, innerStyle: ExtendedViewStyle = {}, textStyle?: ExtendedViewStyle, bgImage?: ImageProps) { + if (every(children, (child)=>isText(child))) { + children = {children} + } else { + if(textStyle) console.warn('Text style will be ignored unless every child of the view is Text node!') + } + return <> + {bgImage && } + {children} + +} + const _View:React.FC<_ViewProps & React.RefAttributes> = React.forwardRef((props: _ViewProps, ref: React.ForwardedRef): React.JSX.Element => { let { style, @@ -211,11 +225,7 @@ const _View:React.FC<_ViewProps & React.RefAttributes> = React.forwardRef(( }, [nodeRef]) const {textStyle, bgImage, innerStyle} = splitStyle(finalStyle) - if (every(children, (child)=>isText(child))) { - children = {children} - } else { - if(textStyle) console.warn('Text style will be ignored unless every child of the view is Text node!') - } + return ( > = React.forwardRef(( {...innerProps} style={innerStyle} > - {bgImage && } - {children} + {wrapChildren(children, innerStyle, textStyle, bgImage)} ) }) From 990fc8660b5e04551240faccdc4917965c74d940 Mon Sep 17 00:00:00 2001 From: shangqunfeng Date: Thu, 23 May 2024 21:27:35 +0800 Subject: [PATCH 05/45] fix(*): fix code --- packages/webpack-plugin/lib/platform/style/wx/index.js | 9 ++++++++- .../lib/runtime/components/react/mpx-text.tsx | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/webpack-plugin/lib/platform/style/wx/index.js b/packages/webpack-plugin/lib/platform/style/wx/index.js index 35c07f0121..2fcc6c2386 100644 --- a/packages/webpack-plugin/lib/platform/style/wx/index.js +++ b/packages/webpack-plugin/lib/platform/style/wx/index.js @@ -350,7 +350,14 @@ module.exports = function getSpec ({ warn, error }) { test: /.*width|height|left|right|top|bottom|radius|margin|padding|spacing|offset|size.*/i, ios: checkCommonValue(ValueType.number), android: checkCommonValue(ValueType.number) - } + }, + { // color 颜色值校验 + test: 'line-height', + ios: ({ prop, value }) => { + console.log(">>> prop, value", prop, value) + }, + android: checkCommonValue(ValueType.color) + }, ] } return spec diff --git a/packages/webpack-plugin/lib/runtime/components/react/mpx-text.tsx b/packages/webpack-plugin/lib/runtime/components/react/mpx-text.tsx index 65c11d9d31..48ab96de59 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/mpx-text.tsx +++ b/packages/webpack-plugin/lib/runtime/components/react/mpx-text.tsx @@ -65,7 +65,7 @@ const _Text: React.FC<_TextProps & React.RefAttributes> = React.forwardRef( return ( Date: Thu, 23 May 2024 22:22:48 +0800 Subject: [PATCH 06/45] fix(*): fix code --- .../webpack-plugin/lib/runtime/components/react/mpx-view.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx index 3267168e5c..85cad05892 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx +++ b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx @@ -118,7 +118,7 @@ function wrapChildren(children: ElementNode, innerStyle: ExtendedViewStyle = {}, const _View:React.FC<_ViewProps & React.RefAttributes> = React.forwardRef((props: _ViewProps, ref: React.ForwardedRef): React.JSX.Element => { let { - style, + style = [], children, hoverStyle, } = props From fbd69d4395b1c8db3d8f7d3a8b8f1e5bab15f8f3 Mon Sep 17 00:00:00 2001 From: shangqunfeng Date: Fri, 24 May 2024 00:11:53 +0800 Subject: [PATCH 07/45] feat(text): fix text style. --- .../lib/platform/style/wx/index.js | 17 +++++++++++++ .../lib/runtime/components/react/mpx-text.tsx | 25 ++++++++++++++++--- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/packages/webpack-plugin/lib/platform/style/wx/index.js b/packages/webpack-plugin/lib/platform/style/wx/index.js index 35c07f0121..52dc7f7a77 100644 --- a/packages/webpack-plugin/lib/platform/style/wx/index.js +++ b/packages/webpack-plugin/lib/platform/style/wx/index.js @@ -208,6 +208,18 @@ module.exports = function getSpec ({ warn, error }) { }) } + const formatLineHeight = ({ prop, value }) => { + if (!numberRegExp.test(value)) { + verifyValues({ prop, value, valueType: ValueType.number }) + return false + } + + return { + prop, + value : !!Number(value) ? `${Math.round(value*100)}%` : value + } + } + const getFontVariant = ({ prop, value }) => { if (/^(font-variant-caps|font-variant-numeric|font-variant-east-asian|font-variant-alternates|font-variant-ligatures)$/.test(prop)) { error(`Property [${prop}] is not supported in React Native environment, please replace [font-variant]!`) @@ -346,6 +358,11 @@ module.exports = function getSpec ({ warn, error }) { ios: checkCommonValue(ValueType.color), android: checkCommonValue(ValueType.color) }, + { // color 颜色值校验 + test: 'line-height', + ios: formatLineHeight, + android: formatLineHeight + }, { // number 值校验 test: /.*width|height|left|right|top|bottom|radius|margin|padding|spacing|offset|size.*/i, ios: checkCommonValue(ValueType.number), diff --git a/packages/webpack-plugin/lib/runtime/components/react/mpx-text.tsx b/packages/webpack-plugin/lib/runtime/components/react/mpx-text.tsx index 65c11d9d31..e654b826f1 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/mpx-text.tsx +++ b/packages/webpack-plugin/lib/runtime/components/react/mpx-text.tsx @@ -4,7 +4,7 @@ * ✘ space * ✘ decode */ -import { Text, TextProps } from 'react-native' +import { Text, TextStyle, TextProps, StyleSheet } from 'react-native' import * as React from 'react' import { useImperativeHandle } from 'react' // @ts-ignore @@ -12,8 +12,11 @@ import useInnerProps from './getInnerListeners'; // @ts-ignore import useNodesRef from '../../useNodesRef' // 引入辅助函数 +type ExtendedTextStyle = TextStyle & { + lineHeight: string | number +}; interface _TextProps extends TextProps { - style?: any; + style?: ExtendedTextStyle; children?: React.ReactNode; selectable?: boolean; ['user-select']?: boolean; @@ -25,9 +28,20 @@ const DEFAULT_STYLE = { fontSize: 16 } +const NUMBER_REGX = /^\d+(\.\d+)?%$/ + +const transformStyle = (styleObj: ExtendedTextStyle) => { + let lineHeight = styleObj.lineHeight + if (lineHeight) return + if (typeof lineHeight === 'string' && NUMBER_REGX.test(lineHeight)) { + lineHeight = ((lineHeight as any).replace('%', '')/100) * (styleObj.fontSize || DEFAULT_STYLE.fontSize) + styleObj['lineHeight'] = lineHeight + } +} + const _Text: React.FC<_TextProps & React.RefAttributes> = React.forwardRef((props: _TextProps, ref: React.ForwardedRef):React.JSX.Element => { const { - style, + style = [], children, selectable, 'user-select': userSelect, @@ -37,6 +51,9 @@ const _Text: React.FC<_TextProps & React.RefAttributes> = React.forwardRef( const measureTimeout = React.useRef | null>(null) + const styleObj = StyleSheet.flatten(style) + transformStyle(styleObj) + const innerProps = useInnerProps(props, {}, [ 'style', 'children', @@ -65,7 +82,7 @@ const _Text: React.FC<_TextProps & React.RefAttributes> = React.forwardRef( return ( Date: Fri, 24 May 2024 00:56:32 +0800 Subject: [PATCH 08/45] fix(view): transform text array. --- .../lib/runtime/components/react/mpx-view.tsx | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx index 85cad05892..bf3149ae79 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx +++ b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx @@ -42,8 +42,7 @@ type GroupData = { [key: string]: ExtendedViewStyle } -function groupBy(style:ExtendedViewStyle, callback: (key: string, val: string) => string ) { - let group:GroupData = {} +function groupBy(style:ExtendedViewStyle, callback: (key: string, val: string) => string, group:GroupData = {}) { for (let key in style) { let val = style[key] let groupKey = callback(key, val) @@ -73,13 +72,17 @@ const imageStyleToProps = (imageStyle: ExtendedViewStyle) => { } -function splitStyle(style: ExtendedViewStyle) { - const { textStyle, imageStyle, innerStyle} = groupBy(style, (key) => { - if (TEXT_STYLE_REGEX.test(key)) - return 'textStyle' - else if (['backgroundImage', 'backgroundSize'].includes(key)) return 'imageStyle' - return 'innerStyle' +function splitStyle(styles: ExtendedViewStyle []) { + let group:GroupData = {} + styles.forEach(style => { + groupBy(style, (key) => { + if (TEXT_STYLE_REGEX.test(key)) + return 'textStyle' + else if (['backgroundImage', 'backgroundSize'].includes(key)) return 'imageStyle' + return 'innerStyle' + }, group) }) + const { textStyle, imageStyle, innerStyle } = group return { textStyle, @@ -201,12 +204,6 @@ const _View:React.FC<_ViewProps & React.RefAttributes> = React.forwardRef(( flexWrap: 'nowrap' } } - - const finalStyle:ExtendedViewStyle = { - ...defaultStyle, - ...styleObj, - ...isHover && StyleSheet.flatten(hoverStyle) - } const { nodeRef } = useNodesRef(props, ref, { defaultStyle @@ -224,8 +221,11 @@ const _View:React.FC<_ViewProps & React.RefAttributes> = React.forwardRef(( } }, [nodeRef]) - const {textStyle, bgImage, innerStyle} = splitStyle(finalStyle) - + const {textStyle, bgImage, innerStyle} = splitStyle([ + defaultStyle, + styleObj, + isHover ? StyleSheet.flatten(hoverStyle) : {} + ]) return ( Date: Fri, 24 May 2024 01:16:13 +0800 Subject: [PATCH 09/45] fix(*): recursion. --- .../lib/runtime/components/react/mpx-view.tsx | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx index bf3149ae79..99cd7a1b38 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx +++ b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx @@ -42,10 +42,15 @@ type GroupData = { [key: string]: ExtendedViewStyle } -function groupBy(style:ExtendedViewStyle, callback: (key: string, val: string) => string, group:GroupData = {}) { +function groupBy(style, callback, group = {}):GroupData { + let groupKey = '' for (let key in style) { let val = style[key] - let groupKey = callback(key, val) + if (typeof val === 'object') { + groupBy(style[key], callback, group) + continue + } + groupKey = callback(key, val) if (!group[groupKey]) { group[groupKey] = {} } @@ -54,6 +59,7 @@ function groupBy(style:ExtendedViewStyle, callback: (key: string, val: string) = return group } + const imageStyleToProps = (imageStyle: ExtendedViewStyle) => { if (!imageStyle) return null let bgImage:ImageProps = { @@ -73,17 +79,12 @@ const imageStyleToProps = (imageStyle: ExtendedViewStyle) => { function splitStyle(styles: ExtendedViewStyle []) { - let group:GroupData = {} - styles.forEach(style => { - groupBy(style, (key) => { - if (TEXT_STYLE_REGEX.test(key)) - return 'textStyle' - else if (['backgroundImage', 'backgroundSize'].includes(key)) return 'imageStyle' - return 'innerStyle' - }, group) - }) - const { textStyle, imageStyle, innerStyle } = group - + const {textStyle, imageStyle, innerStyle} = groupBy(styles, (key) => { + if (TEXT_STYLE_REGEX.test(key)) + return 'textStyle' + else if (['backgroundImage', 'backgroundSize'].includes(key)) return 'imageStyle' + return 'innerStyle' + }, {}) return { textStyle, bgImage: imageStyleToProps(imageStyle), From 4bd1f0bf69266107de8c35f045b57a4ac6119921 Mon Sep 17 00:00:00 2001 From: shangqunfeng Date: Fri, 24 May 2024 08:02:40 +0800 Subject: [PATCH 10/45] fix(*): opt every. --- .../lib/runtime/components/react/mpx-view.tsx | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx index 99cd7a1b38..824c31363a 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx +++ b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx @@ -85,6 +85,7 @@ function splitStyle(styles: ExtendedViewStyle []) { else if (['backgroundImage', 'backgroundSize'].includes(key)) return 'imageStyle' return 'innerStyle' }, {}) + console.log(">>> textStyle, imageStyle, innerStyle", textStyle, imageStyle, innerStyle) return { textStyle, bgImage: imageStyleToProps(imageStyle), @@ -97,15 +98,7 @@ const isText = (children: ElementNode) => { } function every(children: ElementNode, callback: (children: ElementNode) => boolean ) { - let hasSameElement = true - - React.Children.forEach(children, (child) => { - if (!callback(child)) { - hasSameElement = false - } - }) - - return hasSameElement + return React.Children.toArray(children).every((child) => callback(child as ElementNode)) } function wrapChildren(children: ElementNode, innerStyle: ExtendedViewStyle = {}, textStyle?: ExtendedViewStyle, bgImage?: ImageProps) { From ac30a344a1e1c0d285ed4631195e7e06790b9688 Mon Sep 17 00:00:00 2001 From: shangqunfeng Date: Fri, 24 May 2024 08:03:17 +0800 Subject: [PATCH 11/45] fix(*): fix code --- .../webpack-plugin/lib/runtime/components/react/mpx-view.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx index 824c31363a..41d31c72af 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx +++ b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx @@ -85,7 +85,6 @@ function splitStyle(styles: ExtendedViewStyle []) { else if (['backgroundImage', 'backgroundSize'].includes(key)) return 'imageStyle' return 'innerStyle' }, {}) - console.log(">>> textStyle, imageStyle, innerStyle", textStyle, imageStyle, innerStyle) return { textStyle, bgImage: imageStyleToProps(imageStyle), From 06358b1ff67814a466f7d66bfb0ad583c7f198a3 Mon Sep 17 00:00:00 2001 From: shangqunfeng Date: Fri, 24 May 2024 11:08:20 +0800 Subject: [PATCH 12/45] fix(*): fix code --- packages/webpack-plugin/lib/platform/style/wx/index.js | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/packages/webpack-plugin/lib/platform/style/wx/index.js b/packages/webpack-plugin/lib/platform/style/wx/index.js index 2fcc6c2386..35c07f0121 100644 --- a/packages/webpack-plugin/lib/platform/style/wx/index.js +++ b/packages/webpack-plugin/lib/platform/style/wx/index.js @@ -350,14 +350,7 @@ module.exports = function getSpec ({ warn, error }) { test: /.*width|height|left|right|top|bottom|radius|margin|padding|spacing|offset|size.*/i, ios: checkCommonValue(ValueType.number), android: checkCommonValue(ValueType.number) - }, - { // color 颜色值校验 - test: 'line-height', - ios: ({ prop, value }) => { - console.log(">>> prop, value", prop, value) - }, - android: checkCommonValue(ValueType.color) - }, + } ] } return spec From 603f2520c042a67f460f33ff15470fd616882dba Mon Sep 17 00:00:00 2001 From: shangqunfeng Date: Fri, 24 May 2024 11:15:35 +0800 Subject: [PATCH 13/45] fix(*): fix code --- .../lib/runtime/components/react/mpx-text.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/webpack-plugin/lib/runtime/components/react/mpx-text.tsx b/packages/webpack-plugin/lib/runtime/components/react/mpx-text.tsx index 5936a3e0df..4554616001 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/mpx-text.tsx +++ b/packages/webpack-plugin/lib/runtime/components/react/mpx-text.tsx @@ -16,12 +16,12 @@ type ExtendedTextStyle = TextStyle & { lineHeight: string | number }; interface _TextProps extends TextProps { - style?: ExtendedTextStyle; - children?: React.ReactNode; - selectable?: boolean; - ['user-select']?: boolean; - userSelect?: boolean; - useInherit?: boolean; + style?: ExtendedTextStyle + children?: React.ReactNode + selectable?: boolean + ['user-select']?: boolean + userSelect?: boolean + useInherit?: boolean } const DEFAULT_STYLE = { From bf3155a0a8dba3b3e0ed2dd72bb1d9e9b6594a51 Mon Sep 17 00:00:00 2001 From: shangqunfeng Date: Fri, 24 May 2024 11:35:28 +0800 Subject: [PATCH 14/45] fix(*): fix lint. --- packages/webpack-plugin/lib/platform/style/wx/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/webpack-plugin/lib/platform/style/wx/index.js b/packages/webpack-plugin/lib/platform/style/wx/index.js index 52dc7f7a77..b16085fa82 100644 --- a/packages/webpack-plugin/lib/platform/style/wx/index.js +++ b/packages/webpack-plugin/lib/platform/style/wx/index.js @@ -216,7 +216,7 @@ module.exports = function getSpec ({ warn, error }) { return { prop, - value : !!Number(value) ? `${Math.round(value*100)}%` : value + value: isFinite(+value) ? `${Math.round(value * 100)}%` : value } } From 61bf8155af8fc9571c341a2dd72470e7a68d8aa5 Mon Sep 17 00:00:00 2001 From: shangqunfeng Date: Fri, 24 May 2024 12:10:24 +0800 Subject: [PATCH 15/45] fix(*): fix code --- .../lib/runtime/components/react/mpx-view.tsx | 2 +- .../webpack-plugin/lib/runtime/components/react/utils.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx index abb42394ee..510a198358 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx +++ b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx @@ -14,7 +14,7 @@ import useNodesRef from '../../useNodesRef' // 引入辅助函数 import { parseUrl, hasElementType, TEXT_STYLE_REGEX } from './utils' -type ElementNode = Exclude +type ElementNode = React.ReactNode type ExtendedViewStyle = ViewStyle & { backgroundImage?: string diff --git a/packages/webpack-plugin/lib/runtime/components/react/utils.ts b/packages/webpack-plugin/lib/runtime/components/react/utils.ts index d404b84487..9c19a3210e 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/utils.ts +++ b/packages/webpack-plugin/lib/runtime/components/react/utils.ts @@ -1,4 +1,4 @@ -import { useEffect, useRef, Children, ReactElement, FunctionComponent } from 'react' +import { useEffect, useRef, ReactNode } from 'react' import { StyleProp, StyleSheet, TextStyle, ViewStyle } from 'react-native' export const TEXT_STYLE_REGEX = /color|font.*|text.*|letterSpacing|lineHeight|includeFontPadding|writingDirection/ @@ -69,9 +69,9 @@ export const parseUrl = (cssUrl: string = '') => { return match?.[1] } -export const hasElementType = (element: ReactElement, type: string) => { +export const hasElementType = (element: ReactNode, type: string) => { if (!element) return false - return (element.type as FunctionComponent)?.displayName === type + return (element as any)?.type?.displayName === type } export const getRestProps = (transferProps: any = {}, originProps: any = {}, deletePropsKey: any = []) => { From 329afcb27c8fa2f5972b9f36da5fed773b8dd619 Mon Sep 17 00:00:00 2001 From: shangqunfeng Date: Mon, 27 May 2024 22:07:23 +0800 Subject: [PATCH 16/45] fix(*): fix line-height check. --- .../lib/platform/style/wx/index.js | 36 +++++++++++++------ 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/packages/webpack-plugin/lib/platform/style/wx/index.js b/packages/webpack-plugin/lib/platform/style/wx/index.js index b16085fa82..d63b481bf1 100644 --- a/packages/webpack-plugin/lib/platform/style/wx/index.js +++ b/packages/webpack-plugin/lib/platform/style/wx/index.js @@ -53,6 +53,11 @@ module.exports = function getSpec ({ warn, error }) { } } + + function isNumber(val) { + return val && !isNaN(val) + } + // color & number 值校验 const ValueType = { number: 'number', @@ -67,14 +72,26 @@ module.exports = function getSpec ({ warn, error }) { // 校验 value 枚举 是否支持 switch (valueType) { case ValueType.color: - (numberRegExp.test(value)) && warn(`React Native property [${prop}]'s valueType is ${valueType}, we does not set type number`) - colorRegExp.test(value) && warn('React Native color does not support type [lab,lch,oklab,oklch,color-mix,color,hwb,lch,light-dark]') - return value + let isNumberType = numberRegExp.test(value) + let isColorType = colorRegExp.test(value) + isNumberType && warn(`React Native property [${prop}]'s valueType is ${valueType}, we does not set type number`) + isColorType && warn('React Native color does not support type [lab,lch,oklab,oklch,color-mix,color,hwb,lch,light-dark]') + return { + value, + isValid: !isNumberType && !isColorType + } case ValueType.number: - (!numberRegExp.test(value)) && warn(`React Native property [${prop}] unit only supports [rpx,px,%]`) - return value + let isNotNumer = !numberRegExp.test(value) + isNotNumer && warn(`React Native property [${prop}] unit only supports [rpx,px,%]`) + return { + value, + isValid: !isNotNumer + } default: - return value + return { + value, + isValid: true + } } } // 统一校验 value type 值类型 @@ -209,14 +226,11 @@ module.exports = function getSpec ({ warn, error }) { } const formatLineHeight = ({ prop, value }) => { - if (!numberRegExp.test(value)) { - verifyValues({ prop, value, valueType: ValueType.number }) - return false - } + if (!verifyValues({ prop, value, valueType: ValueType.number })) return false return { prop, - value: isFinite(+value) ? `${Math.round(value * 100)}%` : value + value: isNumber(value) ? `${Math.round(value * 100)}%` : value } } From 3953b78135240f625ddd5b91b92b957ada0eba22 Mon Sep 17 00:00:00 2001 From: shangqunfeng Date: Mon, 27 May 2024 22:14:12 +0800 Subject: [PATCH 17/45] fix(*): fix code --- .../lib/platform/style/wx/index.js | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/packages/webpack-plugin/lib/platform/style/wx/index.js b/packages/webpack-plugin/lib/platform/style/wx/index.js index d63b481bf1..569411fb23 100644 --- a/packages/webpack-plugin/lib/platform/style/wx/index.js +++ b/packages/webpack-plugin/lib/platform/style/wx/index.js @@ -71,22 +71,25 @@ module.exports = function getSpec ({ warn, error }) { const verifyValues = ({ prop, value, valueType }) => { // 校验 value 枚举 是否支持 switch (valueType) { - case ValueType.color: - let isNumberType = numberRegExp.test(value) - let isColorType = colorRegExp.test(value) + case ValueType.color: { + + const isNumberType = numberRegExp.test(value) + const isColorType = colorRegExp.test(value) isNumberType && warn(`React Native property [${prop}]'s valueType is ${valueType}, we does not set type number`) isColorType && warn('React Native color does not support type [lab,lch,oklab,oklch,color-mix,color,hwb,lch,light-dark]') return { value, isValid: !isNumberType && !isColorType } - case ValueType.number: - let isNotNumer = !numberRegExp.test(value) - isNotNumer && warn(`React Native property [${prop}] unit only supports [rpx,px,%]`) + } + case ValueType.number: { + const isNumberType = numberRegExp.test(value) + !isNumberType && warn(`React Native property [${prop}] unit only supports [rpx,px,%]`) return { value, - isValid: !isNotNumer + isValid: isNumberType } + } default: return { value, From 3a0bfe6b9f023d7a107088637da1db37090546a1 Mon Sep 17 00:00:00 2001 From: shangqunfeng Date: Tue, 28 May 2024 10:57:34 +0800 Subject: [PATCH 18/45] fix(view): fix view. --- .../lib/runtime/components/react/mpx-view.tsx | 141 +++++++++++++----- .../lib/runtime/components/react/utils.ts | 3 + 2 files changed, 104 insertions(+), 40 deletions(-) diff --git a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx index 510a198358..fae6b4d6ad 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx +++ b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx @@ -4,7 +4,7 @@ * ✔ hover-start-time * ✔ hover-stay-time */ -import { View, Text, ViewStyle, NativeSyntheticEvent, ImageBackground, ImageResizeMode, StyleSheet, Image } from 'react-native' +import { View, Text, ViewStyle, NativeSyntheticEvent, ImageProps, ImageResizeMode, StyleSheet, Image } from 'react-native' import * as React from 'react' // @ts-ignore @@ -12,7 +12,7 @@ import useInnerProps from './getInnerListeners' // @ts-ignore import useNodesRef from '../../useNodesRef' // 引入辅助函数 -import { parseUrl, hasElementType, TEXT_STYLE_REGEX } from './utils' +import { parseUrl, hasElementType, TEXT_STYLE_REGEX, PERCENT_REGX } from './utils' type ElementNode = React.ReactNode @@ -21,14 +21,6 @@ type ExtendedViewStyle = ViewStyle & { backgroundSize?: ImageResizeMode } -type ImageProps = { - resizeMode?: ImageResizeMode - source?: { - uri: string - } -} - - export interface _ViewProps extends ExtendedViewStyle { style?: Array children?: ElementNode @@ -42,14 +34,15 @@ type GroupData = { [key: string]: ExtendedViewStyle } +type Handlers = { + [key: string]: (val: string, innerStyle: ExtendedViewStyle) => void; +} + + function groupBy(style, callback, group = {}):GroupData { let groupKey = '' for (let key in style) { let val = style[key] - if (typeof val === 'object') { - groupBy(style[key], callback, group) - continue - } groupKey = callback(key, val) if (!group[groupKey]) { group[groupKey] = {} @@ -60,36 +53,101 @@ function groupBy(style, callback, group = {}):GroupData { } -const imageStyleToProps = (imageStyle: ExtendedViewStyle) => { + +const applyHandlers = (imageStyle:ExtendedViewStyle, innerStyle:ExtendedViewStyle, handlers: Handlers , context: { props: ImageProps}) => { + + for (let key in imageStyle) { + const handler = handlers[key] + const val = imageStyle[key] + if (handler && val && !handler.call(context, val, innerStyle)) { + break + } + } +} + + +const imageStyleToProps = (imageStyle: ExtendedViewStyle, innerStyle: ExtendedViewStyle) => { if (!imageStyle) return null - let bgImage:ImageProps = { - resizeMode: 'stretch' + // 初始化 + const context: { + props: ImageProps + } = { + props: { + resizeMode: 'stretch', + style: { + ...StyleSheet.absoluteFillObject + } + } } - if (imageStyle['backgroundSize']) { - bgImage['resizeMode'] = imageStyle['backgroundSize'] + + // background-size 转换 + function backgroundSize (val, innerStyle) { + // 枚举值 + if (['cover', 'contain'].includes(val)) { + this.props.resizeMode = val + } else { + let sizeList = val.trim().split(/\s+/) + // 归一化 + if (sizeList.length === 1) { + sizeList.push(sizeList[0]) + } + + const style = sizeList.reduce((style, val, idx) => { + let { width, height } = innerStyle + // 百分比 + if (PERCENT_REGX.test(val)) { + const decimal = parseFloat(val)/100 + if (idx === 0) { + style.width = decimal * width + }else { + style.height = decimal * height + } + }else { + // 数字 + if (idx === 0) { + style.width = val + }else { + style.height = val + } + } + return style + }, {}) + + // 样式合并 + this.props.style = [ + ...this.props.style, + ...style + ] + + } + return true } - if (imageStyle['backgroundImage']){ - const url = parseUrl(imageStyle['backgroundImage']) + + // background-image 转换 + function backgroundImage(val) { + const url = parseUrl(val) if (!url) return null - bgImage['source'] = {uri: url} + this.props.source = {uri: url} + return true } - return bgImage -} + applyHandlers(imageStyle, innerStyle, { + backgroundSize, + backgroundImage, + }, context) + + if (!context?.props?.source) return null + return context.props +} -function splitStyle(styles: ExtendedViewStyle []) { - const {textStyle, imageStyle, innerStyle} = groupBy(styles, (key) => { +function splitStyle(styles: ExtendedViewStyle) { + return groupBy(styles, (key) => { if (TEXT_STYLE_REGEX.test(key)) return 'textStyle' else if (['backgroundImage', 'backgroundSize'].includes(key)) return 'imageStyle' return 'innerStyle' }, {}) - return { - textStyle, - bgImage: imageStyleToProps(imageStyle), - innerStyle - } } const isText = (children: ElementNode) => { @@ -100,16 +158,19 @@ function every(children: ElementNode, callback: (children: ElementNode) => boole return React.Children.toArray(children).every((child) => callback(child as ElementNode)) } -function wrapChildren(children: ElementNode, innerStyle: ExtendedViewStyle = {}, textStyle?: ExtendedViewStyle, bgImage?: ImageProps) { +function wrapChildren(children: ElementNode, innerStyle: ExtendedViewStyle = {}, textStyle?: ExtendedViewStyle, imageStyle?: ExtendedViewStyle) { if (every(children, (child)=>isText(child))) { children = {children} } else { if(textStyle) console.warn('Text style will be ignored unless every child of the view is Text node!') } - return <> - {bgImage && } - {children} - + + const bgImage = imageStyleToProps(imageStyle, innerStyle) + + return [ + bgImage && , + children + ] } const _View:React.FC<_ViewProps & React.RefAttributes> = React.forwardRef((props: _ViewProps, ref: React.ForwardedRef): React.JSX.Element => { @@ -214,11 +275,11 @@ const _View:React.FC<_ViewProps & React.RefAttributes> = React.forwardRef(( } }, [nodeRef]) - const {textStyle, bgImage, innerStyle} = splitStyle([ + const {textStyle, imageStyle, innerStyle} = splitStyle(StyleSheet.flatten([ defaultStyle, styleObj, - isHover ? StyleSheet.flatten(hoverStyle) : {} - ]) + ...(isHover ? hoverStyle : [])] + )) return ( > = React.forwardRef(( {...innerProps} style={innerStyle} > - {wrapChildren(children, innerStyle, textStyle, bgImage)} + {wrapChildren(children, innerStyle, textStyle, imageStyle)} ) }) diff --git a/packages/webpack-plugin/lib/runtime/components/react/utils.ts b/packages/webpack-plugin/lib/runtime/components/react/utils.ts index 9c19a3210e..fc55134e53 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/utils.ts +++ b/packages/webpack-plugin/lib/runtime/components/react/utils.ts @@ -2,6 +2,9 @@ import { useEffect, useRef, ReactNode } from 'react' import { StyleProp, StyleSheet, TextStyle, ViewStyle } from 'react-native' export const TEXT_STYLE_REGEX = /color|font.*|text.*|letterSpacing|lineHeight|includeFontPadding|writingDirection/ + +export const PERCENT_REGX = /%$/ + const URL_REGEX = /url\(["']?(.*?)["']?\)/ export function omit(obj: T, fields: K[]): Omit { From 71330795bc5b45b9d163317f50fc3eb0e94c0424 Mon Sep 17 00:00:00 2001 From: shangqunfeng Date: Tue, 28 May 2024 11:51:17 +0800 Subject: [PATCH 19/45] fix(*): fix code. --- .../lib/runtime/components/react/mpx-view.tsx | 24 ++++++------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx index fae6b4d6ad..29f3e2476c 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx +++ b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx @@ -94,36 +94,26 @@ const imageStyleToProps = (imageStyle: ExtendedViewStyle, innerStyle: ExtendedVi const style = sizeList.reduce((style, val, idx) => { let { width, height } = innerStyle - // 百分比 - if (PERCENT_REGX.test(val)) { - const decimal = parseFloat(val)/100 - if (idx === 0) { - style.width = decimal * width - }else { - style.height = decimal * height - } + + if (idx === 0) { + style.width = PERCENT_REGX.test(val) ? (parseFloat(val)/100)* width : val }else { - // 数字 - if (idx === 0) { - style.width = val - }else { - style.height = val - } + style.height = PERCENT_REGX.test(val) ? (parseFloat(val)/100)* height : val } return style }, {}) // 样式合并 - this.props.style = [ + this.props.style = { ...this.props.style, ...style - ] + } } return true } - // background-image 转换 + // background-image function backgroundImage(val) { const url = parseUrl(val) if (!url) return null From f94c0e00e6651405c7c8164c0e1f3f663ce5abd8 Mon Sep 17 00:00:00 2001 From: shangqunfeng Date: Tue, 28 May 2024 14:13:19 +0800 Subject: [PATCH 20/45] fix(*): fix code --- .../webpack-plugin/lib/runtime/components/react/mpx-text.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/webpack-plugin/lib/runtime/components/react/mpx-text.tsx b/packages/webpack-plugin/lib/runtime/components/react/mpx-text.tsx index 2a48744779..dc998a7116 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/mpx-text.tsx +++ b/packages/webpack-plugin/lib/runtime/components/react/mpx-text.tsx @@ -30,7 +30,7 @@ const PERCENT_REGX = /%$/ const transformStyle = (styleObj: ExtendedTextStyle) => { let { lineHeight } = styleObj if (typeof lineHeight === 'string' && PERCENT_REGX.test(lineHeight)) { - lineHeight = (+lineHeight.replace('%', '')/100) * (styleObj.fontSize || DEFAULT_STYLE.fontSize) + lineHeight = (parseFloat(lineHeight)/100) * (styleObj.fontSize || DEFAULT_STYLE.fontSize) styleObj.lineHeight = lineHeight } } From 3284a6e487f038bf289110e53054490faf61459f Mon Sep 17 00:00:00 2001 From: shangqunfeng Date: Tue, 28 May 2024 16:51:02 +0800 Subject: [PATCH 21/45] fix(*): fix view reg. --- .../lib/runtime/components/react/mpx-view.tsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx index 29f3e2476c..0393c7786e 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx +++ b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx @@ -38,6 +38,7 @@ type Handlers = { [key: string]: (val: string, innerStyle: ExtendedViewStyle) => void; } +const IMAGE_STYLE_REGEX = /^background(Image|Size|Repeat|Position)$/ function groupBy(style, callback, group = {}):GroupData { let groupKey = '' @@ -52,8 +53,6 @@ function groupBy(style, callback, group = {}):GroupData { return group } - - const applyHandlers = (imageStyle:ExtendedViewStyle, innerStyle:ExtendedViewStyle, handlers: Handlers , context: { props: ImageProps}) => { for (let key in imageStyle) { @@ -65,7 +64,6 @@ const applyHandlers = (imageStyle:ExtendedViewStyle, innerStyle:ExtendedViewStyl } } - const imageStyleToProps = (imageStyle: ExtendedViewStyle, innerStyle: ExtendedViewStyle) => { if (!imageStyle) return null // 初始化 @@ -135,7 +133,7 @@ function splitStyle(styles: ExtendedViewStyle) { return groupBy(styles, (key) => { if (TEXT_STYLE_REGEX.test(key)) return 'textStyle' - else if (['backgroundImage', 'backgroundSize'].includes(key)) return 'imageStyle' + else if (IMAGE_STYLE_REGEX.test(key)) return 'imageStyle' return 'innerStyle' }, {}) } From 93257dfcf713610267151f9249e27aa1a6421135 Mon Sep 17 00:00:00 2001 From: shangqunfeng Date: Tue, 28 May 2024 23:37:36 +0800 Subject: [PATCH 22/45] fix(*): fix code --- .../lib/runtime/components/react/mpx-view.tsx | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx index 0393c7786e..48e9998285 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx +++ b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx @@ -171,13 +171,11 @@ const _View:React.FC<_ViewProps & React.RefAttributes> = React.forwardRef(( const measureTimeout = React.useRef | null>(null) const dataRef = React.useRef<{ - startTimestamp: number, startTimer?: ReturnType stayTimer?: ReturnType - props: any }>({ - startTimestamp: 0, - props: props + startTimer: 0, + stayTimer: 0 }) React.useEffect(() => { @@ -185,7 +183,7 @@ const _View:React.FC<_ViewProps & React.RefAttributes> = React.forwardRef(( dataRef.current.startTimer && clearTimeout(dataRef.current.startTimer) dataRef.current.stayTimer && clearTimeout(dataRef.current.stayTimer) } - }, [dataRef]) + }, []) const setStartTimer = () => { const { hoverStyle, 'hover-start-time': hoverStartTime = 50 } = dataRef.current.props From 98e7234378cfdf0901b03a38d587a7e2b1bc25bf Mon Sep 17 00:00:00 2001 From: shangqunfeng Date: Tue, 28 May 2024 23:48:52 +0800 Subject: [PATCH 23/45] fix(*): fix code --- .../lib/platform/style/wx/index.js | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/packages/webpack-plugin/lib/platform/style/wx/index.js b/packages/webpack-plugin/lib/platform/style/wx/index.js index 569411fb23..d4831db5b7 100644 --- a/packages/webpack-plugin/lib/platform/style/wx/index.js +++ b/packages/webpack-plugin/lib/platform/style/wx/index.js @@ -53,11 +53,6 @@ module.exports = function getSpec ({ warn, error }) { } } - - function isNumber(val) { - return val && !isNaN(val) - } - // color & number 值校验 const ValueType = { number: 'number', @@ -68,6 +63,7 @@ module.exports = function getSpec ({ warn, error }) { const numberRegExp = /^\s*(\d+(\.\d+)?)(rpx|px|%)?\s*$/ // RN 不支持的颜色格式 const colorRegExp = /^\s*(lab|lch|oklab|oklch|color-mix|color|hwb|lch|light-dark).*$/ + const verifyValues = ({ prop, value, valueType }) => { // 校验 value 枚举 是否支持 switch (valueType) { @@ -79,7 +75,7 @@ module.exports = function getSpec ({ warn, error }) { isColorType && warn('React Native color does not support type [lab,lch,oklab,oklch,color-mix,color,hwb,lch,light-dark]') return { value, - isValid: !isNumberType && !isColorType + valid: !isNumberType && !isColorType } } case ValueType.number: { @@ -87,13 +83,13 @@ module.exports = function getSpec ({ warn, error }) { !isNumberType && warn(`React Native property [${prop}] unit only supports [rpx,px,%]`) return { value, - isValid: isNumberType + valid: isNumberType } } default: return { value, - isValid: true + valid: true } } } @@ -153,7 +149,7 @@ module.exports = function getSpec ({ warn, error }) { const valueType = keyMap[prop] const dashProp = hump2dash(prop) // 校验 value 类型 - const value = verifyValues({ prop, value: values[idx], valueType }) + const value = verifyValues({ prop, value: values[idx], valueType }).value if (isIllegalValue({ prop: dashProp, value })) { // 过滤不支持 value unsupportedValueError({ prop: dashProp, value }) @@ -229,11 +225,11 @@ module.exports = function getSpec ({ warn, error }) { } const formatLineHeight = ({ prop, value }) => { - if (!verifyValues({ prop, value, valueType: ValueType.number })) return false + if (!verifyValues({ prop, value, valueType: ValueType.number }).value) return false return { prop, - value: isNumber(value) ? `${Math.round(value * 100)}%` : value + value: /\d+(\.\d+)?$/.test(value) ? `${Math.round(value * 100)}%` : value } } From 9dd4bde921a12efc7bf45f758a29717b9225dd7c Mon Sep 17 00:00:00 2001 From: shangqunfeng Date: Wed, 29 May 2024 00:26:04 +0800 Subject: [PATCH 24/45] fix(*): fix code --- .../lib/runtime/components/react/mpx-text.tsx | 2 +- .../lib/runtime/components/react/mpx-view.tsx | 109 +++++++----------- 2 files changed, 43 insertions(+), 68 deletions(-) diff --git a/packages/webpack-plugin/lib/runtime/components/react/mpx-text.tsx b/packages/webpack-plugin/lib/runtime/components/react/mpx-text.tsx index 90b6148203..988da8800a 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/mpx-text.tsx +++ b/packages/webpack-plugin/lib/runtime/components/react/mpx-text.tsx @@ -8,6 +8,7 @@ import { Text, TextStyle, TextProps, StyleSheet } from 'react-native' import React, { useRef, useEffect, forwardRef, ReactNode, ForwardedRef } from 'react'; import useInnerProps from './getInnerListeners'; import useNodesRef from '../../useNodesRef' // 引入辅助函数 +import { PERCENT_REGX } from './utils' type ExtendedTextStyle = Omit & { lineHeight?: string | number @@ -26,7 +27,6 @@ const DEFAULT_STYLE = { fontSize: 16 } -const PERCENT_REGX = /%$/ const transformStyle = (styleObj: ExtendedTextStyle) => { let { lineHeight } = styleObj diff --git a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx index 3a31d6ee7e..e1e7899eb3 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx +++ b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx @@ -25,6 +25,9 @@ export interface _ViewProps extends ExtendedViewStyle { style?: Array children?: ElementNode hoverStyle: Array + ['hover-start-time']: number + ['hover-stay-time']: number + 'enable-offset'?: boolean bindtouchstart?: (event: NativeSyntheticEvent | unknown) => void bindtouchmove?: (event: NativeSyntheticEvent | unknown) => void bindtouchend?: (event: NativeSyntheticEvent | unknown) => void @@ -34,9 +37,7 @@ type GroupData = { [key: string]: ExtendedViewStyle } -type Handlers = { - [key: string]: (val: string, innerStyle: ExtendedViewStyle) => void; -} +type Handler = (val: string, imageProps: ImageProps) => void const IMAGE_STYLE_REGEX = /^background(Image|Size|Repeat|Position)$/ @@ -53,36 +54,30 @@ function groupBy(style, callback, group = {}):GroupData { return group } -const applyHandlers = (imageStyle:ExtendedViewStyle, innerStyle:ExtendedViewStyle, handlers: Handlers , context: { props: ImageProps}) => { - - for (let key in imageStyle) { +const applyHandlers = (handlers: Handler[] , options) => { + const [ imageStyle, imageProps ] = options + for (let key in handlers) { const handler = handlers[key] - const val = imageStyle[key] - if (handler && val && !handler.call(context, val, innerStyle)) { - break - } + const val = imageStyle[handler.name] + handler && val && handler(val, imageProps) } } -const imageStyleToProps = (imageStyle: ExtendedViewStyle, innerStyle: ExtendedViewStyle) => { +const imageStyleToProps = (imageStyle: ExtendedViewStyle) => { if (!imageStyle) return null // 初始化 - const context: { - props: ImageProps - } = { - props: { - resizeMode: 'stretch', - style: { - ...StyleSheet.absoluteFillObject - } + const imageProps: ImageProps = { + style: { + resizeMode: 'cover', + ...StyleSheet.absoluteFillObject } } // background-size 转换 - function backgroundSize (val, innerStyle) { + function backgroundSize (val, imageProps) { // 枚举值 if (['cover', 'contain'].includes(val)) { - this.props.resizeMode = val + imageProps.style.resizeMode = val } else { let sizeList = val.trim().split(/\s+/) // 归一化 @@ -91,42 +86,32 @@ const imageStyleToProps = (imageStyle: ExtendedViewStyle, innerStyle: ExtendedVi } const style = sizeList.reduce((style, val, idx) => { - let { width, height } = innerStyle - if (idx === 0) { - style.width = PERCENT_REGX.test(val) ? (parseFloat(val)/100)* width : val + style.width = PERCENT_REGX.test(val) ? val : +val }else { - style.height = PERCENT_REGX.test(val) ? (parseFloat(val)/100)* height : val + style.height = PERCENT_REGX.test(val) ? val : +val } return style }, {}) // 样式合并 - this.props.style = { - ...this.props.style, + imageProps.style = { + ...imageProps.style, ...style } - } - return true } - - // background-image - function backgroundImage(val) { + // background-image转换为source + function backgroundImage(val, imageProps) { const url = parseUrl(val) if (!url) return null - this.props.source = {uri: url} - return true + imageProps.source = {uri: url} } - applyHandlers(imageStyle, innerStyle, { - backgroundSize, - backgroundImage, - }, context) + applyHandlers([ backgroundSize, backgroundImage ], [imageStyle, imageProps]) - if (!context?.props?.source) return null - - return context.props + if (!imageProps?.source) return null + return imageProps } function splitStyle(styles: ExtendedViewStyle) { @@ -146,14 +131,14 @@ function every(children: ElementNode, callback: (children: ElementNode) => boole return Children.toArray(children).every((child) => callback(child as ElementNode)) } -function wrapChildren(children: ElementNode, innerStyle: ExtendedViewStyle = {}, textStyle?: ExtendedViewStyle, imageStyle?: ExtendedViewStyle) { +function wrapChildren(children: ElementNode, textStyle?: ExtendedViewStyle, imageStyle?: ExtendedViewStyle) { if (every(children, (child)=>isText(child))) { children = {children} } else { if(textStyle) console.warn('Text style will be ignored unless every child of the view is Text node!') } - const bgImage = imageStyleToProps(imageStyle, innerStyle) + const bgImage = imageStyleToProps(imageStyle) return [ bgImage && , @@ -166,6 +151,8 @@ const _View = forwardRef((props: _ViewProps, ref: ForwardedRef): React.JSX. style = [], children, hoverStyle, + 'hover-start-time': hoverStartTime = 50, + 'hover-stay-time': hoverStayTime = 400, 'enable-offset': enableOffset } = props @@ -193,40 +180,30 @@ const _View = forwardRef((props: _ViewProps, ref: ForwardedRef): React.JSX. }) const dataRef = useRef<{ - startTimestamp: number, startTimer?: ReturnType stayTimer?: ReturnType props: any - }>({ - startTimestamp: 0, - props: props - }) + }>({}) useEffect(() => { return () => { dataRef.current.startTimer && clearTimeout(dataRef.current.startTimer) dataRef.current.stayTimer && clearTimeout(dataRef.current.stayTimer) } - }, [dataRef]) + }, []) const setStartTimer = () => { - const { hoverStyle, 'hover-start-time': hoverStartTime = 50 } = dataRef.current.props - if (hoverStyle) { - dataRef.current.startTimer && clearTimeout(dataRef.current.startTimer) - dataRef.current.startTimer = setTimeout(() => { - setIsHover(() => true) - }, hoverStartTime) - } + dataRef.current.startTimer && clearTimeout(dataRef.current.startTimer) + dataRef.current.startTimer = setTimeout(() => { + setIsHover(() => true) + }, hoverStartTime) } const setStayTimer = () => { - const { hoverStyle, 'hover-stay-time': hoverStayTime = 400 } = dataRef.current.props - if (hoverStyle) { - dataRef.current.stayTimer && clearTimeout(dataRef.current.stayTimer) - dataRef.current.stayTimer = setTimeout(() => { - setIsHover(() => false) - }, hoverStayTime) - } + dataRef.current.stayTimer && clearTimeout(dataRef.current.stayTimer) + dataRef.current.stayTimer = setTimeout(() => { + setIsHover(() => false) + }, hoverStayTime) } function onTouchStart(e: NativeSyntheticEvent){ @@ -262,9 +239,7 @@ const _View = forwardRef((props: _ViewProps, ref: ForwardedRef): React.JSX. 'hoverStyle', 'hover-class', 'enable-offset' - ], { - touchable: true - }) + ]) React.useEffect(() => { setTimeout(() => { @@ -290,7 +265,7 @@ const _View = forwardRef((props: _ViewProps, ref: ForwardedRef): React.JSX. {...innerProps} style={innerStyle} > - {wrapChildren(children, innerStyle, textStyle, imageStyle)} + {wrapChildren(children, textStyle, imageStyle)} ) }) From 4865b94a63cb5677b444e9227870b0c15c631a7b Mon Sep 17 00:00:00 2001 From: shangqunfeng Date: Wed, 29 May 2024 00:36:54 +0800 Subject: [PATCH 25/45] fix(*): fix code --- packages/webpack-plugin/lib/platform/style/wx/index.js | 1 - .../webpack-plugin/lib/runtime/components/react/mpx-view.tsx | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/webpack-plugin/lib/platform/style/wx/index.js b/packages/webpack-plugin/lib/platform/style/wx/index.js index d4831db5b7..33344c5db2 100644 --- a/packages/webpack-plugin/lib/platform/style/wx/index.js +++ b/packages/webpack-plugin/lib/platform/style/wx/index.js @@ -68,7 +68,6 @@ module.exports = function getSpec ({ warn, error }) { // 校验 value 枚举 是否支持 switch (valueType) { case ValueType.color: { - const isNumberType = numberRegExp.test(value) const isColorType = colorRegExp.test(value) isNumberType && warn(`React Native property [${prop}]'s valueType is ${valueType}, we does not set type number`) diff --git a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx index e1e7899eb3..0d934f6a79 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx +++ b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx @@ -58,7 +58,7 @@ const applyHandlers = (handlers: Handler[] , options) => { const [ imageStyle, imageProps ] = options for (let key in handlers) { const handler = handlers[key] - const val = imageStyle[handler.name] + const val = imageStyle[handler?.name] handler && val && handler(val, imageProps) } } @@ -110,7 +110,7 @@ const imageStyleToProps = (imageStyle: ExtendedViewStyle) => { applyHandlers([ backgroundSize, backgroundImage ], [imageStyle, imageProps]) - if (!imageProps?.source) return null + if (!imageProps?.source) return null return imageProps } From b793e3b9a2082b094ea3224d8897d9644ca88487 Mon Sep 17 00:00:00 2001 From: shangqunfeng Date: Wed, 29 May 2024 01:07:13 +0800 Subject: [PATCH 26/45] fix(*): fix code --- .../lib/runtime/components/react/mpx-view.tsx | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx index 0d934f6a79..59e6588cd2 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx +++ b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx @@ -58,7 +58,7 @@ const applyHandlers = (handlers: Handler[] , options) => { const [ imageStyle, imageProps ] = options for (let key in handlers) { const handler = handlers[key] - const val = imageStyle[handler?.name] + const val = imageStyle[handler.name] handler && val && handler(val, imageProps) } } @@ -108,9 +108,10 @@ const imageStyleToProps = (imageStyle: ExtendedViewStyle) => { imageProps.source = {uri: url} } - applyHandlers([ backgroundSize, backgroundImage ], [imageStyle, imageProps]) + applyHandlers([ backgroundSize, backgroundImage ],[imageStyle, imageProps]) - if (!imageProps?.source) return null + if (!imageProps?.source) return null + return imageProps } @@ -140,8 +141,11 @@ function wrapChildren(children: ElementNode, textStyle?: ExtendedViewStyle, imag const bgImage = imageStyleToProps(imageStyle) + console.log(">>> bgImage", bgImage) + + return [ - bgImage && , + bgImage && , children ] } @@ -165,7 +169,7 @@ const _View = forwardRef((props: _ViewProps, ref: ForwardedRef): React.JSX. // 打平 style 数组 const styleObj:ExtendedViewStyle = StyleSheet.flatten(style) // 默认样式 - const defaultStyle = { + const defaultStyle:ExtendedViewStyle = { // flex 布局相关的默认样式 ...styleObj.display === 'flex' && { flexDirection: 'row', @@ -182,8 +186,7 @@ const _View = forwardRef((props: _ViewProps, ref: ForwardedRef): React.JSX. const dataRef = useRef<{ startTimer?: ReturnType stayTimer?: ReturnType - props: any - }>({}) + }>() useEffect(() => { return () => { @@ -253,7 +256,7 @@ const _View = forwardRef((props: _ViewProps, ref: ForwardedRef): React.JSX. } }, [nodeRef]) - const {textStyle, imageStyle, innerStyle} = splitStyle(StyleSheet.flatten([ + const {textStyle, imageStyle, innerStyle} = splitStyle(StyleSheet.flatten([ defaultStyle, styleObj, ...(isHover ? hoverStyle : [])] From 00eaca30fe1b8c1062c0ab8717b318f8091f3bbc Mon Sep 17 00:00:00 2001 From: shangqunfeng Date: Wed, 29 May 2024 01:07:35 +0800 Subject: [PATCH 27/45] fix(*): fix code --- .../lib/runtime/components/react/mpx-view.tsx | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx index 59e6588cd2..f02a5835e6 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx +++ b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx @@ -110,8 +110,8 @@ const imageStyleToProps = (imageStyle: ExtendedViewStyle) => { applyHandlers([ backgroundSize, backgroundImage ],[imageStyle, imageProps]) - if (!imageProps?.source) return null - + if (!imageProps?.source) return null + return imageProps } @@ -141,9 +141,6 @@ function wrapChildren(children: ElementNode, textStyle?: ExtendedViewStyle, imag const bgImage = imageStyleToProps(imageStyle) - console.log(">>> bgImage", bgImage) - - return [ bgImage && , children From 39d5854001158f68021a49f95013121dff59a29d Mon Sep 17 00:00:00 2001 From: shangqunfeng Date: Wed, 29 May 2024 10:47:00 +0800 Subject: [PATCH 28/45] fix(*): fix code --- .../webpack-plugin/lib/runtime/components/react/mpx-view.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx index f02a5835e6..c96eee1191 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx +++ b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx @@ -160,7 +160,6 @@ const _View = forwardRef((props: _ViewProps, ref: ForwardedRef): React.JSX. const [isHover, setIsHover] = useState(false) const measureTimeout = React.useRef | null>(null) - const layoutRef = useRef({}) // 打平 style 数组 @@ -183,7 +182,7 @@ const _View = forwardRef((props: _ViewProps, ref: ForwardedRef): React.JSX. const dataRef = useRef<{ startTimer?: ReturnType stayTimer?: ReturnType - }>() + }>({}) useEffect(() => { return () => { From f7b7bb6ae9d47f861ad7d61a44accf15fc9958c5 Mon Sep 17 00:00:00 2001 From: shangqunfeng Date: Wed, 29 May 2024 15:14:25 +0800 Subject: [PATCH 29/45] fix(*): fix code --- .../lib/runtime/components/react/mpx-view.tsx | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx index c96eee1191..863de50571 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx +++ b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx @@ -37,7 +37,7 @@ type GroupData = { [key: string]: ExtendedViewStyle } -type Handler = (val: string, imageProps: ImageProps) => void +type Handler = ([imageStyle, imageProps]: [ExtendedViewStyle, ImageProps]) => void const IMAGE_STYLE_REGEX = /^background(Image|Size|Repeat|Position)$/ @@ -54,12 +54,9 @@ function groupBy(style, callback, group = {}):GroupData { return group } -const applyHandlers = (handlers: Handler[] , options) => { - const [ imageStyle, imageProps ] = options - for (let key in handlers) { - const handler = handlers[key] - const val = imageStyle[handler.name] - handler && val && handler(val, imageProps) +const applyHandlers = (handlers: Handler[] , args) => { + for (let handler of handlers) { + handler(args) } } @@ -74,7 +71,9 @@ const imageStyleToProps = (imageStyle: ExtendedViewStyle) => { } // background-size 转换 - function backgroundSize (val, imageProps) { + function backgroundSize ([imageStyle, imageProps]) { + let val = imageStyle.backgroundSize + if (!val) return // 枚举值 if (['cover', 'contain'].includes(val)) { imageProps.style.resizeMode = val @@ -102,7 +101,9 @@ const imageStyleToProps = (imageStyle: ExtendedViewStyle) => { } } // background-image转换为source - function backgroundImage(val, imageProps) { + function backgroundImage([imageStyle, imageProps]) { + let val = imageStyle.backgroundImage + if (!val) return const url = parseUrl(val) if (!url) return null imageProps.source = {uri: url} From 7c40d2f385e5fecb8ea8e8a221e2d02eb3dad6c1 Mon Sep 17 00:00:00 2001 From: shangqunfeng Date: Wed, 29 May 2024 15:39:21 +0800 Subject: [PATCH 30/45] fix(*): fix code --- .../webpack-plugin/lib/runtime/components/react/mpx-view.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx index 863de50571..7000428fec 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx +++ b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx @@ -196,14 +196,14 @@ const _View = forwardRef((props: _ViewProps, ref: ForwardedRef): React.JSX. dataRef.current.startTimer && clearTimeout(dataRef.current.startTimer) dataRef.current.startTimer = setTimeout(() => { setIsHover(() => true) - }, hoverStartTime) + }, +hoverStartTime) } const setStayTimer = () => { dataRef.current.stayTimer && clearTimeout(dataRef.current.stayTimer) dataRef.current.stayTimer = setTimeout(() => { setIsHover(() => false) - }, hoverStayTime) + }, +hoverStayTime) } function onTouchStart(e: NativeSyntheticEvent){ From e7c82093df586b3fb4744b33244c5076c7277895 Mon Sep 17 00:00:00 2001 From: shangqunfeng Date: Thu, 30 May 2024 18:06:17 +0800 Subject: [PATCH 31/45] fix(*): add image. --- .../lib/runtime/components/react/mpx-view.tsx | 161 +++++++++++++----- 1 file changed, 115 insertions(+), 46 deletions(-) diff --git a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx index 7000428fec..3d227a5bfa 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx +++ b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx @@ -4,7 +4,7 @@ * ✔ hover-start-time * ✔ hover-stay-time */ -import { View, Text, ViewStyle, NativeSyntheticEvent, ImageProps, ImageResizeMode, StyleSheet, Image } from 'react-native' +import { View, Text, ViewStyle, NativeSyntheticEvent, ImageProps, ImageResizeMode, StyleSheet, Image, ImageURISource, ImageStyle } from 'react-native' import React, { useRef, useState, useEffect, forwardRef, Children, ForwardedRef } from 'react' // @ts-ignore @@ -37,7 +37,7 @@ type GroupData = { [key: string]: ExtendedViewStyle } -type Handler = ([imageStyle, imageProps]: [ExtendedViewStyle, ImageProps]) => void +type Handler = ([imageStyle, imageProps, originImage, layoutInfo]: [ExtendedViewStyle, ImageProps, any, any]) => void const IMAGE_STYLE_REGEX = /^background(Image|Size|Repeat|Position)$/ @@ -60,7 +60,13 @@ const applyHandlers = (handlers: Handler[] , args) => { } } -const imageStyleToProps = (imageStyle: ExtendedViewStyle) => { +const isLayout = (style: ExtendedViewStyle = {}) => { + if (!style?.backgroundImage) return false + const [width, height] = style.backgroundSize || [] + return (PERCENT_REGX.test(height) && width === 'auto') || (PERCENT_REGX.test(width) && height === 'auto') +} + +const imageStyleToProps = (imageStyle: ExtendedViewStyle, originImage, layoutInfo) => { if (!imageStyle) return null // 初始化 const imageProps: ImageProps = { @@ -71,37 +77,69 @@ const imageStyleToProps = (imageStyle: ExtendedViewStyle) => { } // background-size 转换 - function backgroundSize ([imageStyle, imageProps]) { + function backgroundSize ([imageStyle, imageProps, originImage, layoutInfo]) { let val = imageStyle.backgroundSize if (!val) return // 枚举值 - if (['cover', 'contain'].includes(val)) { + + if (['cover', 'contain'].includes(val[0])) { imageProps.style.resizeMode = val - } else { - let sizeList = val.trim().split(/\s+/) + } else{ + let sizeList = val.slice() // 归一化 if (sizeList.length === 1) { sizeList.push(sizeList[0]) } - - const style = sizeList.reduce((style, val, idx) => { - if (idx === 0) { - style.width = PERCENT_REGX.test(val) ? val : +val - }else { - style.height = PERCENT_REGX.test(val) ? val : +val + const [width, height] = sizeList + let newWidth = 0, newHeight = 0 + + const { width: originWidth, height: originHeight } = originImage || {} + + // 若background-size为auto 则不设置宽高 + // if (width === 'auto' && height === 'auto') return + if (width === 'auto' && height === 'auto' && originImage) { + newHeight = originHeight + newWidth = originWidth + } else if (width === 'auto' && originImage) { + // 1. auto % - 真实的宽度 + if (PERCENT_REGX.test(height)) { + if (!layoutInfo) return + const { height: layoutHeight} = layoutInfo + + newHeight = (parseFloat(height) / 100) * layoutHeight + newWidth = newHeight * originWidth / originHeight + } else { // 2. auto px/rpx - 根据比例计算 + newHeight = height + newWidth = newHeight * originWidth / originHeight } - return style - }, {}) - + }else if (height === 'auto' && originImage) { // 10px auto + // 1. % auto - 真实的宽度 + if (PERCENT_REGX.test(width)) { + if (!layoutInfo) return + const { width: layoutWidth} = layoutInfo + newWidth = (parseFloat(width) / 100) * layoutWidth + newHeight = newWidth * originHeight / originWidth + } else { // 2. px/rpx auto - 根据比例计算 + newWidth = width + newHeight = newWidth * originHeight / originWidth + } + } else { + // 数值类型设置为 stretch + imageProps.style.resizeMode = 'stretch' + newWidth = width === 'auto' ? (originImage?.width || width) : PERCENT_REGX.test(width) ? width : +width + newHeight = height === 'auto' ? (originImage?.height || height) : PERCENT_REGX.test(height) ? height : +height + } + // 样式合并 imageProps.style = { ...imageProps.style, - ...style + width: newWidth, + height: newHeight } } } // background-image转换为source - function backgroundImage([imageStyle, imageProps]) { + function backgroundImage([imageStyle, imageProps, ...others]) { let val = imageStyle.backgroundImage if (!val) return const url = parseUrl(val) @@ -109,13 +147,52 @@ const imageStyleToProps = (imageStyle: ExtendedViewStyle) => { imageProps.source = {uri: url} } - applyHandlers([ backgroundSize, backgroundImage ],[imageStyle, imageProps]) + applyHandlers([ backgroundSize, backgroundImage ],[imageStyle, imageProps, originImage, layoutInfo]) if (!imageProps?.source) return null return imageProps } +function wrapImage(imageStyle, layoutInfo) { + const [isLoading, setIsLoading] = useState(false) + const [originImage, setOriginImage] = useState(null); + + const bgImage = imageStyleToProps(imageStyle, originImage, layoutInfo) + if (!imageStyle) return null + + useEffect(() => { + const { style, source } = bgImage + let { uri } = (source || {}) as ImageURISource + let { height, width } = (style || {}) as ImageStyle + + if (!uri) return; + // if ((height=== 'auto' && width === 'auto') || ![height, width].includes('auto')) return + if (![height, width].includes('auto')) return + setIsLoading(true) + Image.getSize(uri, (width, height) => { + setIsLoading(false) + setOriginImage({ + width, + height + }) + }, () => { + setIsLoading(false) + setOriginImage(null) + }) + return () => { + setIsLoading(false) + setOriginImage(null) + } + }, [imageStyle.backgroundImage, imageStyle.backgroundSize]) + + + return bgImage && !isLoading && + + +} + + function splitStyle(styles: ExtendedViewStyle) { return groupBy(styles, (key) => { if (TEXT_STYLE_REGEX.test(key)) @@ -133,17 +210,14 @@ function every(children: ElementNode, callback: (children: ElementNode) => boole return Children.toArray(children).every((child) => callback(child as ElementNode)) } -function wrapChildren(children: ElementNode, textStyle?: ExtendedViewStyle, imageStyle?: ExtendedViewStyle) { +function wrapChildren(children: ElementNode, textStyle?: ExtendedViewStyle, imageStyle?: ExtendedViewStyle, layoutInfo?: any) { if (every(children, (child)=>isText(child))) { children = {children} } else { if(textStyle) console.warn('Text style will be ignored unless every child of the view is Text node!') } - const bgImage = imageStyleToProps(imageStyle) - - return [ - bgImage && , + return [wrapImage(imageStyle, layoutInfo), children ] } @@ -159,7 +233,8 @@ const _View = forwardRef((props: _ViewProps, ref: ForwardedRef): React.JSX. } = props const [isHover, setIsHover] = useState(false) - const measureTimeout = React.useRef | null>(null) + + const [layoutInfo, setLayoutInfo] = useState(null) const layoutRef = useRef({}) @@ -218,15 +293,27 @@ const _View = forwardRef((props: _ViewProps, ref: ForwardedRef): React.JSX. setStayTimer() } - const onLayout = () => { + const onLayout = (res) => { + const layout = res?.nativeEvent?.layout + layout && setLayoutInfo({ + height: layout.height, + width: layout.width + }) nodeRef.current?.measure((x, y, width, height, offsetLeft, offsetTop) => { layoutRef.current = { x, y, width, height, offsetLeft, offsetTop } }) } + const {textStyle, imageStyle, innerStyle} = splitStyle(StyleSheet.flatten([ + defaultStyle, + styleObj, + ...(isHover ? hoverStyle : [])] + )) + const innerProps = useInnerProps(props, { ref: nodeRef, - ...(enableOffset ? { onLayout } : {}), + onLayout, + ...((enableOffset || isLayout(imageStyle)) ? { onLayout } : {}), ...(hoverStyle && { bindtouchstart: onTouchStart, bindtouchend: onTouchEnd @@ -241,31 +328,13 @@ const _View = forwardRef((props: _ViewProps, ref: ForwardedRef): React.JSX. 'enable-offset' ]) - React.useEffect(() => { - setTimeout(() => { - nodeRef.current = nodeRef.current.measure((x, y, width, height, offsetLeft, offsetTop) => { - nodeRef.current = { x, y, width, height, offsetLeft, offsetTop } - }) - }) - return () => { - measureTimeout.current && clearTimeout(measureTimeout.current); - measureTimeout.current = null - } - }, [nodeRef]) - - const {textStyle, imageStyle, innerStyle} = splitStyle(StyleSheet.flatten([ - defaultStyle, - styleObj, - ...(isHover ? hoverStyle : [])] - )) - return ( - {wrapChildren(children, textStyle, imageStyle)} + {wrapChildren(children, textStyle, imageStyle, layoutInfo)} ) }) From 1f8dd368afbe3c28f072800c83a11122ea7655d8 Mon Sep 17 00:00:00 2001 From: shangqunfeng Date: Thu, 30 May 2024 19:33:18 +0800 Subject: [PATCH 32/45] fix(*): fix code --- .../lib/platform/style/wx/index.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/webpack-plugin/lib/platform/style/wx/index.js b/packages/webpack-plugin/lib/platform/style/wx/index.js index 33344c5db2..9f6956862b 100644 --- a/packages/webpack-plugin/lib/platform/style/wx/index.js +++ b/packages/webpack-plugin/lib/platform/style/wx/index.js @@ -68,21 +68,21 @@ module.exports = function getSpec ({ warn, error }) { // 校验 value 枚举 是否支持 switch (valueType) { case ValueType.color: { - const isNumberType = numberRegExp.test(value) - const isColorType = colorRegExp.test(value) - isNumberType && warn(`React Native property [${prop}]'s valueType is ${valueType}, we does not set type number`) - isColorType && warn('React Native color does not support type [lab,lch,oklab,oklch,color-mix,color,hwb,lch,light-dark]') + const isNumber = numberRegExp.test(value) + const isUnsupporttedColor = colorRegExp.test(value) + isNumber && warn(`React Native property [${prop}]'s valueType is ${valueType}, we does not set type number`) + isUnsupporttedColor && warn('React Native color does not support type [lab,lch,oklab,oklch,color-mix,color,hwb,lch,light-dark]') return { value, - valid: !isNumberType && !isColorType + valid: !isNumber && !isUnsupporttedColor } } case ValueType.number: { - const isNumberType = numberRegExp.test(value) - !isNumberType && warn(`React Native property [${prop}] unit only supports [rpx,px,%]`) + const isNumber = numberRegExp.test(value) + !isNumber && warn(`React Native property [${prop}] unit only supports [rpx,px,%]`) return { value, - valid: isNumberType + valid: isNumber } } default: From 593939de73b431eb5b772b87d3551bd474faf693 Mon Sep 17 00:00:00 2001 From: shangqunfeng Date: Thu, 30 May 2024 19:47:51 +0800 Subject: [PATCH 33/45] fix(*): fix code --- packages/webpack-plugin/lib/platform/style/wx/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/webpack-plugin/lib/platform/style/wx/index.js b/packages/webpack-plugin/lib/platform/style/wx/index.js index 9f6956862b..2f4d6b1539 100644 --- a/packages/webpack-plugin/lib/platform/style/wx/index.js +++ b/packages/webpack-plugin/lib/platform/style/wx/index.js @@ -224,7 +224,7 @@ module.exports = function getSpec ({ warn, error }) { } const formatLineHeight = ({ prop, value }) => { - if (!verifyValues({ prop, value, valueType: ValueType.number }).value) return false + if (!verifyValues({ prop, value, valueType: ValueType.number }).valid) return false return { prop, From d523cf452be31c4050e2580d9a06c539cd4f6a9f Mon Sep 17 00:00:00 2001 From: shangqunfeng Date: Fri, 31 May 2024 10:25:05 +0800 Subject: [PATCH 34/45] fix(*): fix view. --- .../lib/platform/style/wx/index.js | 3 +- .../lib/runtime/components/react/mpx-view.tsx | 228 ++++++++++-------- 2 files changed, 132 insertions(+), 99 deletions(-) diff --git a/packages/webpack-plugin/lib/platform/style/wx/index.js b/packages/webpack-plugin/lib/platform/style/wx/index.js index 2f4d6b1539..9c044e027a 100644 --- a/packages/webpack-plugin/lib/platform/style/wx/index.js +++ b/packages/webpack-plugin/lib/platform/style/wx/index.js @@ -148,7 +148,8 @@ module.exports = function getSpec ({ warn, error }) { const valueType = keyMap[prop] const dashProp = hump2dash(prop) // 校验 value 类型 - const value = verifyValues({ prop, value: values[idx], valueType }).value + verifyValues({ prop, value: values[idx], valueType }) + const value = values[idx] if (isIllegalValue({ prop: dashProp, value })) { // 过滤不支持 value unsupportedValueError({ prop: dashProp, value }) diff --git a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx index 3d227a5bfa..2a399f8fc2 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx +++ b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx @@ -37,7 +37,7 @@ type GroupData = { [key: string]: ExtendedViewStyle } -type Handler = ([imageStyle, imageProps, originImage, layoutInfo]: [ExtendedViewStyle, ImageProps, any, any]) => void +type Handler = (...args: any []) => void const IMAGE_STYLE_REGEX = /^background(Image|Size|Repeat|Position)$/ @@ -56,17 +56,38 @@ function groupBy(style, callback, group = {}):GroupData { const applyHandlers = (handlers: Handler[] , args) => { for (let handler of handlers) { - handler(args) + handler(...args) } } -const isLayout = (style: ExtendedViewStyle = {}) => { - if (!style?.backgroundImage) return false - const [width, height] = style.backgroundSize || [] +const isLayoutEvent = (style) => { + const [width, height] = style.sizeList || [] return (PERCENT_REGX.test(height) && width === 'auto') || (PERCENT_REGX.test(width) && height === 'auto') } -const imageStyleToProps = (imageStyle: ExtendedViewStyle, originImage, layoutInfo) => { +/** + * h - 用户设置的高度 + * lh - 容器的高度 + * ratio - 原始图片的宽高比 + * **/ +function calculateSize(h, lh, ratio) { + let height, width + if (PERCENT_REGX.test(h)) { // auto px/rpx + if (!lh) return null + height = (parseFloat(h) / 100) * lh + width = height * ratio + } else { // 2. auto px/rpx - 根据比例计算 + height = h + width = height * ratio + } + + return { + width, + height + } +} + +const imageStyleToProps = (imageStyle: ExtendedViewStyle, imageSize, layoutInfo, preImageInfo) => { if (!imageStyle) return null // 初始化 const imageProps: ImageProps = { @@ -77,59 +98,38 @@ const imageStyleToProps = (imageStyle: ExtendedViewStyle, originImage, layoutInf } // background-size 转换 - function backgroundSize ([imageStyle, imageProps, originImage, layoutInfo]) { - let val = imageStyle.backgroundSize - if (!val) return + function backgroundSize (imageStyle, imageProps, preImageInfo, imageSize, layoutInfo) { + let sizeList = preImageInfo.sizeList + if (!sizeList) return // 枚举值 - if (['cover', 'contain'].includes(val[0])) { - imageProps.style.resizeMode = val - } else{ - let sizeList = val.slice() - // 归一化 - if (sizeList.length === 1) { - sizeList.push(sizeList[0]) - } + if (['cover', 'contain'].includes(sizeList[0])) { + imageProps.style.resizeMode = sizeList[0] + } else { const [width, height] = sizeList let newWidth = 0, newHeight = 0 - const { width: originWidth, height: originHeight } = originImage || {} - - // 若background-size为auto 则不设置宽高 - // if (width === 'auto' && height === 'auto') return - if (width === 'auto' && height === 'auto' && originImage) { - newHeight = originHeight - newWidth = originWidth - } else if (width === 'auto' && originImage) { - // 1. auto % - 真实的宽度 - if (PERCENT_REGX.test(height)) { - if (!layoutInfo) return - const { height: layoutHeight} = layoutInfo - - newHeight = (parseFloat(height) / 100) * layoutHeight - newWidth = newHeight * originWidth / originHeight - } else { // 2. auto px/rpx - 根据比例计算 - newHeight = height - newWidth = newHeight * originWidth / originHeight - } - }else if (height === 'auto' && originImage) { // 10px auto - // 1. % auto - 真实的宽度 - if (PERCENT_REGX.test(width)) { - if (!layoutInfo) return - const { width: layoutWidth} = layoutInfo - newWidth = (parseFloat(width) / 100) * layoutWidth - newHeight = newWidth * originHeight / originWidth - } else { // 2. px/rpx auto - 根据比例计算 - newWidth = width - newHeight = newWidth * originHeight / originWidth - } - } else { + const { width: imageSizeWidth, height: imageSizeHeight } = imageSize || {} + + if (width === 'auto' && height === 'auto' && imageSize) { // 均为auto + newHeight = imageSizeHeight + newWidth = imageSizeWidth + } else if (width === 'auto' && imageSize) { // auto px/rpx/% + const dimensions = calculateSize(height, layoutInfo?.height, imageSizeWidth / imageSizeHeight) + if (!dimensions) return null + newWidth = dimensions.width + newHeight = dimensions.height + }else if (height === 'auto' && imageSize) { // auto px/rpx/% + const dimensions = calculateSize(width, layoutInfo?.width, imageSizeHeight / imageSizeWidth) + if (!dimensions) return null + newHeight = dimensions.width + newWidth = dimensions.height + } else { // 数值类型 // 数值类型设置为 stretch imageProps.style.resizeMode = 'stretch' - newWidth = width === 'auto' ? (originImage?.width || width) : PERCENT_REGX.test(width) ? width : +width - newHeight = height === 'auto' ? (originImage?.height || height) : PERCENT_REGX.test(height) ? height : +height + newWidth = PERCENT_REGX.test(width) ? width : +width + newHeight = PERCENT_REGX.test(height) ? height : +height } - // 样式合并 imageProps.style = { ...imageProps.style, @@ -138,57 +138,95 @@ const imageStyleToProps = (imageStyle: ExtendedViewStyle, originImage, layoutInf } } } + // background-image转换为source - function backgroundImage([imageStyle, imageProps, ...others]) { + function backgroundImage(imageStyle, imageProps, preImageInfo) { let val = imageStyle.backgroundImage - if (!val) return - const url = parseUrl(val) - if (!url) return null - imageProps.source = {uri: url} + let src = preImageInfo.src ? preImageInfo.src : parseUrl(val) + if (!src) return null + imageProps.src = src } - applyHandlers([ backgroundSize, backgroundImage ],[imageStyle, imageProps, originImage, layoutInfo]) - - if (!imageProps?.source) return null + applyHandlers([ backgroundSize, backgroundImage ],[imageStyle, imageProps, preImageInfo, imageSize, layoutInfo]) + if (!imageProps?.src) return null return imageProps } -function wrapImage(imageStyle, layoutInfo) { - const [isLoading, setIsLoading] = useState(false) - const [originImage, setOriginImage] = useState(null); - const bgImage = imageStyleToProps(imageStyle, originImage, layoutInfo) - if (!imageStyle) return null +function preParseImage(imageStyle:ExtendedViewStyle) { + const { backgroundImage, backgroundSize = [] } = imageStyle + const src = parseUrl(backgroundImage) + if (!src) return null + + let sizeList = backgroundSize.slice() + + sizeList.length === 1 && sizeList.push(sizeList[0]) + + return { + src, + sizeList + } +} + +function wrapImage(imageStyle) { + const [show, setShow] = useState(false) + const [imageSize, setImageSize] = useState(null); + const [layoutInfo, setLayoutInfo] = useState(null) + + // 预解析 + const preImageInfo = preParseImage(imageStyle) + + if (!preImageInfo) return null + + // 判断是否可挂载onLayout + const isViewLayout = isLayoutEvent(preImageInfo) + + let bgImage = null + + if (show) { + bgImage = imageStyleToProps(imageStyle, imageSize, layoutInfo, preImageInfo) + } useEffect(() => { - const { style, source } = bgImage - let { uri } = (source || {}) as ImageURISource - let { height, width } = (style || {}) as ImageStyle - - if (!uri) return; - // if ((height=== 'auto' && width === 'auto') || ![height, width].includes('auto')) return - if (![height, width].includes('auto')) return - setIsLoading(true) - Image.getSize(uri, (width, height) => { - setIsLoading(false) - setOriginImage({ - width, - height - }) + const { src, sizeList = [] } = preImageInfo + + if (!src) return + if (!sizeList.includes('auto')) { + setShow(true) + return + } + Image.getSize(src, (width, height) => { + setImageSize({ width, height }); + //1. 当需要绑定onLayout 2. 获取到布局信息 + (!isViewLayout || layoutInfo) && setShow(true) }, () => { - setIsLoading(false) - setOriginImage(null) + setShow(false) + setImageSize(null) + setLayoutInfo(null) }) return () => { - setIsLoading(false) - setOriginImage(null) + setShow(false) + setImageSize(null) + setLayoutInfo(null) } - }, [imageStyle.backgroundImage, imageStyle.backgroundSize]) + }, [imageStyle.backgroundImage]) - return bgImage && !isLoading && - + const onLayout = (res) => { + const layout = res?.nativeEvent?.layout + setLayoutInfo({ + height: layout.height, + width: layout.width + }) + imageSize && setShow(true) + } + + const props = isViewLayout ? { + onLayout + } : {} + return + {show && } } @@ -210,14 +248,14 @@ function every(children: ElementNode, callback: (children: ElementNode) => boole return Children.toArray(children).every((child) => callback(child as ElementNode)) } -function wrapChildren(children: ElementNode, textStyle?: ExtendedViewStyle, imageStyle?: ExtendedViewStyle, layoutInfo?: any) { +function wrapChildren(children: ElementNode, textStyle?: ExtendedViewStyle, imageStyle?: ExtendedViewStyle) { if (every(children, (child)=>isText(child))) { children = {children} } else { if(textStyle) console.warn('Text style will be ignored unless every child of the view is Text node!') } - return [wrapImage(imageStyle, layoutInfo), + return [imageStyle && wrapImage(imageStyle), children ] } @@ -234,8 +272,6 @@ const _View = forwardRef((props: _ViewProps, ref: ForwardedRef): React.JSX. const [isHover, setIsHover] = useState(false) - const [layoutInfo, setLayoutInfo] = useState(null) - const layoutRef = useRef({}) // 打平 style 数组 @@ -276,6 +312,7 @@ const _View = forwardRef((props: _ViewProps, ref: ForwardedRef): React.JSX. const setStayTimer = () => { dataRef.current.stayTimer && clearTimeout(dataRef.current.stayTimer) + dataRef.current.startTimer && clearTimeout(dataRef.current.startTimer) dataRef.current.stayTimer = setTimeout(() => { setIsHover(() => false) }, +hoverStayTime) @@ -293,12 +330,8 @@ const _View = forwardRef((props: _ViewProps, ref: ForwardedRef): React.JSX. setStayTimer() } - const onLayout = (res) => { - const layout = res?.nativeEvent?.layout - layout && setLayoutInfo({ - height: layout.height, - width: layout.width - }) + const onLayout = () => { + nodeRef.current?.measure((x, y, width, height, offsetLeft, offsetTop) => { layoutRef.current = { x, y, width, height, offsetLeft, offsetTop } }) @@ -312,8 +345,7 @@ const _View = forwardRef((props: _ViewProps, ref: ForwardedRef): React.JSX. const innerProps = useInnerProps(props, { ref: nodeRef, - onLayout, - ...((enableOffset || isLayout(imageStyle)) ? { onLayout } : {}), + ...enableOffset ? { onLayout } : {}, ...(hoverStyle && { bindtouchstart: onTouchStart, bindtouchend: onTouchEnd @@ -334,7 +366,7 @@ const _View = forwardRef((props: _ViewProps, ref: ForwardedRef): React.JSX. {...innerProps} style={innerStyle} > - {wrapChildren(children, textStyle, imageStyle, layoutInfo)} + {wrapChildren(children, textStyle, imageStyle)} ) }) From 20dc6077a45ac14e27b03cfedc29157571e9cfe0 Mon Sep 17 00:00:00 2001 From: shangqunfeng Date: Fri, 31 May 2024 10:29:51 +0800 Subject: [PATCH 35/45] fix(*): fix code --- .../webpack-plugin/lib/runtime/components/react/mpx-view.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx index 2a399f8fc2..9fcfca218b 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx +++ b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx @@ -73,7 +73,6 @@ const isLayoutEvent = (style) => { function calculateSize(h, lh, ratio) { let height, width if (PERCENT_REGX.test(h)) { // auto px/rpx - if (!lh) return null height = (parseFloat(h) / 100) * lh width = height * ratio } else { // 2. auto px/rpx - 根据比例计算 @@ -116,12 +115,10 @@ const imageStyleToProps = (imageStyle: ExtendedViewStyle, imageSize, layoutInfo, newWidth = imageSizeWidth } else if (width === 'auto' && imageSize) { // auto px/rpx/% const dimensions = calculateSize(height, layoutInfo?.height, imageSizeWidth / imageSizeHeight) - if (!dimensions) return null newWidth = dimensions.width newHeight = dimensions.height }else if (height === 'auto' && imageSize) { // auto px/rpx/% const dimensions = calculateSize(width, layoutInfo?.width, imageSizeHeight / imageSizeWidth) - if (!dimensions) return null newHeight = dimensions.width newWidth = dimensions.height } else { // 数值类型 From c5c31eccea901d1912d1d46da509782732940c96 Mon Sep 17 00:00:00 2001 From: shangqunfeng Date: Fri, 31 May 2024 16:01:00 +0800 Subject: [PATCH 36/45] fix(*): fix istext. --- .../lib/runtime/components/react/mpx-view.tsx | 7 ++++--- .../webpack-plugin/lib/runtime/components/react/utils.ts | 5 ----- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx index 9fcfca218b..8eb74f5bba 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx +++ b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx @@ -12,7 +12,7 @@ import useInnerProps from './getInnerListeners' // @ts-ignore import useNodesRef from '../../useNodesRef' // 引入辅助函数 -import { parseUrl, hasElementType, TEXT_STYLE_REGEX, PERCENT_REGX } from './utils' +import { parseUrl, TEXT_STYLE_REGEX, PERCENT_REGX } from './utils' type ElementNode = React.ReactNode @@ -237,8 +237,9 @@ function splitStyle(styles: ExtendedViewStyle) { }, {}) } -const isText = (children: ElementNode) => { - return hasElementType(children, 'mpx-text') || hasElementType(children, 'Text') +const isText = (ele: ElementNode) => { + const displayName = ele?.type?.displayName + return displayName === 'mpx-text' || displayName === 'Text' } function every(children: ElementNode, callback: (children: ElementNode) => boolean ) { diff --git a/packages/webpack-plugin/lib/runtime/components/react/utils.ts b/packages/webpack-plugin/lib/runtime/components/react/utils.ts index fc55134e53..df532841c4 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/utils.ts +++ b/packages/webpack-plugin/lib/runtime/components/react/utils.ts @@ -72,11 +72,6 @@ export const parseUrl = (cssUrl: string = '') => { return match?.[1] } -export const hasElementType = (element: ReactNode, type: string) => { - if (!element) return false - return (element as any)?.type?.displayName === type -} - export const getRestProps = (transferProps: any = {}, originProps: any = {}, deletePropsKey: any = []) => { return { ...transferProps, From 4e987ff8a0bf6a9067408e9f2d13a04c9955894e Mon Sep 17 00:00:00 2001 From: shangqunfeng Date: Fri, 31 May 2024 17:50:16 +0800 Subject: [PATCH 37/45] fix(*): fix varify. --- .../lib/platform/style/wx/index.js | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/packages/webpack-plugin/lib/platform/style/wx/index.js b/packages/webpack-plugin/lib/platform/style/wx/index.js index 9c044e027a..91366e17df 100644 --- a/packages/webpack-plugin/lib/platform/style/wx/index.js +++ b/packages/webpack-plugin/lib/platform/style/wx/index.js @@ -72,24 +72,15 @@ module.exports = function getSpec ({ warn, error }) { const isUnsupporttedColor = colorRegExp.test(value) isNumber && warn(`React Native property [${prop}]'s valueType is ${valueType}, we does not set type number`) isUnsupporttedColor && warn('React Native color does not support type [lab,lch,oklab,oklch,color-mix,color,hwb,lch,light-dark]') - return { - value, - valid: !isNumber && !isUnsupporttedColor - } + return !isNumber && !isUnsupporttedColor } case ValueType.number: { const isNumber = numberRegExp.test(value) !isNumber && warn(`React Native property [${prop}] unit only supports [rpx,px,%]`) - return { - value, - valid: isNumber - } + return isNumber } default: - return { - value, - valid: true - } + return true } } // 统一校验 value type 值类型 @@ -225,7 +216,7 @@ module.exports = function getSpec ({ warn, error }) { } const formatLineHeight = ({ prop, value }) => { - if (!verifyValues({ prop, value, valueType: ValueType.number }).valid) return false + if (!verifyValues({ prop, value, valueType: ValueType.number })) return false return { prop, From b5124ef56460a36c0eea1b261c702339ee83c6bb Mon Sep 17 00:00:00 2001 From: shangqunfeng Date: Fri, 31 May 2024 17:53:09 +0800 Subject: [PATCH 38/45] fix(*): fix ts. --- .../lib/runtime/components/react/mpx-view.tsx | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx index 8eb74f5bba..e4d558dbd7 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx +++ b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx @@ -5,7 +5,7 @@ * ✔ hover-stay-time */ import { View, Text, ViewStyle, NativeSyntheticEvent, ImageProps, ImageResizeMode, StyleSheet, Image, ImageURISource, ImageStyle } from 'react-native' -import React, { useRef, useState, useEffect, forwardRef, Children, ForwardedRef } from 'react' +import React, { useRef, useState, useEffect, forwardRef, Children, ForwardedRef, ReactNode } from 'react' // @ts-ignore import useInnerProps from './getInnerListeners' @@ -14,7 +14,6 @@ import useNodesRef from '../../useNodesRef' // 引入辅助函数 import { parseUrl, TEXT_STYLE_REGEX, PERCENT_REGX } from './utils' -type ElementNode = React.ReactNode type ExtendedViewStyle = ViewStyle & { backgroundImage?: string @@ -23,7 +22,7 @@ type ExtendedViewStyle = ViewStyle & { export interface _ViewProps extends ExtendedViewStyle { style?: Array - children?: ElementNode + children?: ReactNode hoverStyle: Array ['hover-start-time']: number ['hover-stay-time']: number @@ -237,16 +236,16 @@ function splitStyle(styles: ExtendedViewStyle) { }, {}) } -const isText = (ele: ElementNode) => { +const isText = (ele: ReactNode) => { const displayName = ele?.type?.displayName return displayName === 'mpx-text' || displayName === 'Text' } -function every(children: ElementNode, callback: (children: ElementNode) => boolean ) { - return Children.toArray(children).every((child) => callback(child as ElementNode)) +function every(children: ReactNode, callback: (children: ReactNode) => boolean ) { + return Children.toArray(children).every((child) => callback(child as ReactNode)) } -function wrapChildren(children: ElementNode, textStyle?: ExtendedViewStyle, imageStyle?: ExtendedViewStyle) { +function wrapChildren(children: ReactNode, textStyle?: ExtendedViewStyle, imageStyle?: ExtendedViewStyle) { if (every(children, (child)=>isText(child))) { children = {children} } else { From 9aecbc4971175047b649f9a581991d1a84b74e57 Mon Sep 17 00:00:00 2001 From: shangqunfeng Date: Sat, 1 Jun 2024 00:55:01 +0800 Subject: [PATCH 39/45] fix(*): fix view. --- .../lib/runtime/components/react/mpx-view.tsx | 136 ++++++++---------- .../lib/runtime/components/react/utils.ts | 2 +- 2 files changed, 60 insertions(+), 78 deletions(-) diff --git a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx index e4d558dbd7..dceda89593 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx +++ b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx @@ -59,7 +59,7 @@ const applyHandlers = (handlers: Handler[] , args) => { } } -const isLayoutEvent = (style) => { +const checkNeedLayout = (style) => { const [width, height] = style.sizeList || [] return (PERCENT_REGX.test(height) && width === 'auto') || (PERCENT_REGX.test(width) && height === 'auto') } @@ -72,6 +72,7 @@ const isLayoutEvent = (style) => { function calculateSize(h, lh, ratio) { let height, width if (PERCENT_REGX.test(h)) { // auto px/rpx + if (!lh) return null height = (parseFloat(h) / 100) * lh width = height * ratio } else { // 2. auto px/rpx - 根据比例计算 @@ -85,6 +86,52 @@ function calculateSize(h, lh, ratio) { } } +// background-size 转换 +function backgroundSize (imageProps, preImageInfo, imageSize, layoutInfo) { + let sizeList = preImageInfo.sizeList + if (!sizeList) return + // 枚举值 + if (['cover', 'contain'].includes(sizeList[0])) { + imageProps.style.resizeMode = sizeList[0] + } else { + const [width, height] = sizeList + let newWidth = 0, newHeight = 0 + + const { width: imageSizeWidth, height: imageSizeHeight } = imageSize || {} + + if (width === 'auto' && height === 'auto' && imageSize) { // 均为auto + newHeight = imageSizeHeight + newWidth = imageSizeWidth + } else if (width === 'auto' && imageSize) { // auto px/rpx/% + const dimensions = calculateSize(height, layoutInfo?.height, imageSizeWidth / imageSizeHeight) + if (!dimensions) return + newWidth = dimensions.width + newHeight = dimensions.height + }else if (height === 'auto' && imageSize) { // auto px/rpx/% + const dimensions = calculateSize(width, layoutInfo?.width, imageSizeHeight / imageSizeWidth) + if (!dimensions) return + newHeight = dimensions.width + newWidth = dimensions.height + } else { // 数值类型 + // 数值类型设置为 stretch + imageProps.style.resizeMode = 'stretch' + newWidth = PERCENT_REGX.test(width) ? width : +width + newHeight = PERCENT_REGX.test(height) ? height : +height + } + // 样式合并 + imageProps.style = { + ...imageProps.style, + width: newWidth, + height: newHeight + } + } +} + +// background-image转换为source +function backgroundImage(imageProps, preImageInfo) { + imageProps.src = preImageInfo.src +} + const imageStyleToProps = (imageStyle: ExtendedViewStyle, imageSize, layoutInfo, preImageInfo) => { if (!imageStyle) return null // 初始化 @@ -95,67 +142,18 @@ const imageStyleToProps = (imageStyle: ExtendedViewStyle, imageSize, layoutInfo, } } - // background-size 转换 - function backgroundSize (imageStyle, imageProps, preImageInfo, imageSize, layoutInfo) { - let sizeList = preImageInfo.sizeList - if (!sizeList) return - // 枚举值 - - if (['cover', 'contain'].includes(sizeList[0])) { - imageProps.style.resizeMode = sizeList[0] - } else { - const [width, height] = sizeList - let newWidth = 0, newHeight = 0 - - const { width: imageSizeWidth, height: imageSizeHeight } = imageSize || {} - - if (width === 'auto' && height === 'auto' && imageSize) { // 均为auto - newHeight = imageSizeHeight - newWidth = imageSizeWidth - } else if (width === 'auto' && imageSize) { // auto px/rpx/% - const dimensions = calculateSize(height, layoutInfo?.height, imageSizeWidth / imageSizeHeight) - newWidth = dimensions.width - newHeight = dimensions.height - }else if (height === 'auto' && imageSize) { // auto px/rpx/% - const dimensions = calculateSize(width, layoutInfo?.width, imageSizeHeight / imageSizeWidth) - newHeight = dimensions.width - newWidth = dimensions.height - } else { // 数值类型 - // 数值类型设置为 stretch - imageProps.style.resizeMode = 'stretch' - newWidth = PERCENT_REGX.test(width) ? width : +width - newHeight = PERCENT_REGX.test(height) ? height : +height - } - // 样式合并 - imageProps.style = { - ...imageProps.style, - width: newWidth, - height: newHeight - } - } - } - - // background-image转换为source - function backgroundImage(imageStyle, imageProps, preImageInfo) { - let val = imageStyle.backgroundImage - let src = preImageInfo.src ? preImageInfo.src : parseUrl(val) - if (!src) return null - imageProps.src = src - } - - applyHandlers([ backgroundSize, backgroundImage ],[imageStyle, imageProps, preImageInfo, imageSize, layoutInfo]) + applyHandlers([ backgroundSize, backgroundImage ],[imageProps, preImageInfo, imageSize, layoutInfo]) if (!imageProps?.src) return null - return imageProps } function preParseImage(imageStyle:ExtendedViewStyle) { - const { backgroundImage, backgroundSize = [] } = imageStyle + const { backgroundImage, backgroundSize = [ "auto" ] } = imageStyle const src = parseUrl(backgroundImage) if (!src) return null - let sizeList = backgroundSize.slice() + let sizeList = backgroundSize.slice() as string [] sizeList.length === 1 && sizeList.push(sizeList[0]) @@ -167,7 +165,7 @@ function preParseImage(imageStyle:ExtendedViewStyle) { function wrapImage(imageStyle) { const [show, setShow] = useState(false) - const [imageSize, setImageSize] = useState(null); + const [imageSize, setImageSize] = useState(null) const [layoutInfo, setLayoutInfo] = useState(null) // 预解析 @@ -176,16 +174,10 @@ function wrapImage(imageStyle) { if (!preImageInfo) return null // 判断是否可挂载onLayout - const isViewLayout = isLayoutEvent(preImageInfo) - - let bgImage = null - - if (show) { - bgImage = imageStyleToProps(imageStyle, imageSize, layoutInfo, preImageInfo) - } + const needLayout = checkNeedLayout(preImageInfo) useEffect(() => { - const { src, sizeList = [] } = preImageInfo + const { src, sizeList } = preImageInfo if (!src) return if (!sizeList.includes('auto')) { @@ -195,38 +187,28 @@ function wrapImage(imageStyle) { Image.getSize(src, (width, height) => { setImageSize({ width, height }); //1. 当需要绑定onLayout 2. 获取到布局信息 - (!isViewLayout || layoutInfo) && setShow(true) - }, () => { - setShow(false) - setImageSize(null) - setLayoutInfo(null) + (!needLayout || layoutInfo) && setShow(true) }) return () => { setShow(false) setImageSize(null) setLayoutInfo(null) } - }, [imageStyle.backgroundImage]) - + }, [preImageInfo.src]) const onLayout = (res) => { - const layout = res?.nativeEvent?.layout + const layout = res?.nativeEvent?.layout || {} setLayoutInfo({ height: layout.height, width: layout.width }) imageSize && setShow(true) } - - const props = isViewLayout ? { - onLayout - } : {} - return - {show && } + return + {show && } } - function splitStyle(styles: ExtendedViewStyle) { return groupBy(styles, (key) => { if (TEXT_STYLE_REGEX.test(key)) diff --git a/packages/webpack-plugin/lib/runtime/components/react/utils.ts b/packages/webpack-plugin/lib/runtime/components/react/utils.ts index df532841c4..80ad82afb9 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/utils.ts +++ b/packages/webpack-plugin/lib/runtime/components/react/utils.ts @@ -3,7 +3,7 @@ import { StyleProp, StyleSheet, TextStyle, ViewStyle } from 'react-native' export const TEXT_STYLE_REGEX = /color|font.*|text.*|letterSpacing|lineHeight|includeFontPadding|writingDirection/ -export const PERCENT_REGX = /%$/ +export const PERCENT_REGX = /\d+(\.\d+)?%$/ const URL_REGEX = /url\(["']?(.*?)["']?\)/ From 7d06c2c890a4613b8cfd69ef5865962f9489b43a Mon Sep 17 00:00:00 2001 From: shangqunfeng Date: Sat, 1 Jun 2024 01:06:56 +0800 Subject: [PATCH 40/45] fix(*): fix format. --- .../lib/runtime/components/react/mpx-view.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx index dceda89593..acda2a7e69 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx +++ b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx @@ -132,8 +132,7 @@ function backgroundImage(imageProps, preImageInfo) { imageProps.src = preImageInfo.src } -const imageStyleToProps = (imageStyle: ExtendedViewStyle, imageSize, layoutInfo, preImageInfo) => { - if (!imageStyle) return null +const imageStyleToProps = (preImageInfo, imageSize, layoutInfo) => { // 初始化 const imageProps: ImageProps = { style: { @@ -205,8 +204,8 @@ function wrapImage(imageStyle) { imageSize && setShow(true) } return - {show && } - + {show && } + } function splitStyle(styles: ExtendedViewStyle) { From 5f00d756e80c01a421c3bc9b9875e92a5830e2cb Mon Sep 17 00:00:00 2001 From: shangqunfeng Date: Sat, 1 Jun 2024 10:41:02 +0800 Subject: [PATCH 41/45] fix(*): fix code --- .../lib/runtime/components/react/mpx-view.tsx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx index acda2a7e69..aa5753f060 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx +++ b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx @@ -99,20 +99,23 @@ function backgroundSize (imageProps, preImageInfo, imageSize, layoutInfo) { const { width: imageSizeWidth, height: imageSizeHeight } = imageSize || {} - if (width === 'auto' && height === 'auto' && imageSize) { // 均为auto + if (width === 'auto' && height === 'auto') { // 均为auto + if (!imageSize) return newHeight = imageSizeHeight newWidth = imageSizeWidth - } else if (width === 'auto' && imageSize) { // auto px/rpx/% + } else if (width === 'auto') { // auto px/rpx/% + if (!imageSize) return const dimensions = calculateSize(height, layoutInfo?.height, imageSizeWidth / imageSizeHeight) if (!dimensions) return newWidth = dimensions.width newHeight = dimensions.height - }else if (height === 'auto' && imageSize) { // auto px/rpx/% + }else if (height === 'auto') { // auto px/rpx/% + if (!imageSize) return const dimensions = calculateSize(width, layoutInfo?.width, imageSizeHeight / imageSizeWidth) if (!dimensions) return newHeight = dimensions.width newWidth = dimensions.height - } else { // 数值类型 + } else { // 数值类型 // 数值类型设置为 stretch imageProps.style.resizeMode = 'stretch' newWidth = PERCENT_REGX.test(width) ? width : +width From a4647176965cd5741ab1a2b125d13690011b8f8b Mon Sep 17 00:00:00 2001 From: shangqunfeng Date: Sun, 2 Jun 2024 13:04:45 +0800 Subject: [PATCH 42/45] fix(*): fix code --- .../lib/runtime/components/react/mpx-view.tsx | 57 ++++++++++++------- 1 file changed, 35 insertions(+), 22 deletions(-) diff --git a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx index aa5753f060..c64630c466 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx +++ b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx @@ -60,6 +60,7 @@ const applyHandlers = (handlers: Handler[] , args) => { } const checkNeedLayout = (style) => { + if (!style) return false const [width, height] = style.sizeList || [] return (PERCENT_REGX.test(height) && width === 'auto') || (PERCENT_REGX.test(width) && height === 'auto') } @@ -151,6 +152,8 @@ const imageStyleToProps = (preImageInfo, imageSize, layoutInfo) => { function preParseImage(imageStyle:ExtendedViewStyle) { + if (!imageStyle) return null + const { backgroundImage, backgroundSize = [ "auto" ] } = imageStyle const src = parseUrl(backgroundImage) if (!src) return null @@ -166,48 +169,58 @@ function preParseImage(imageStyle:ExtendedViewStyle) { } function wrapImage(imageStyle) { - const [show, setShow] = useState(false) - const [imageSize, setImageSize] = useState(null) - const [layoutInfo, setLayoutInfo] = useState(null) + const show = useRef(false) + const imageSize = useRef(null) + const layoutInfo = useRef(null) + const [_, forceUpdate] = useState({}) // 预解析 const preImageInfo = preParseImage(imageStyle) - if (!preImageInfo) return null // 判断是否可挂载onLayout const needLayout = checkNeedLayout(preImageInfo) + const { src, sizeList = [] } = preImageInfo || {} useEffect(() => { - const { src, sizeList } = preImageInfo - - if (!src) return - if (!sizeList.includes('auto')) { - setShow(true) - return - } + if (!src || sizeList.length === 0 || !sizeList.includes('auto')) return + Image.getSize(src, (width, height) => { - setImageSize({ width, height }); + + imageSize.current = {width, height} //1. 当需要绑定onLayout 2. 获取到布局信息 - (!needLayout || layoutInfo) && setShow(true) + if (!needLayout || layoutInfo.current) { + show.current = true + forceUpdate({}) + } }) return () => { - setShow(false) - setImageSize(null) - setLayoutInfo(null) + show.current = false + imageSize.current = null + layoutInfo.current = null } - }, [preImageInfo.src]) + }, [preImageInfo?.src]) + + if (!preImageInfo) return null + + if (!sizeList.includes('auto')) { + show.current = true + } const onLayout = (res) => { const layout = res?.nativeEvent?.layout || {} - setLayoutInfo({ + layoutInfo.current = { height: layout.height, width: layout.width - }) - imageSize && setShow(true) + } + if (imageSize.current) { + show.current = true + forceUpdate({}) + } } + return - {show && } + {show.current && } } @@ -236,7 +249,7 @@ function wrapChildren(children: ReactNode, textStyle?: ExtendedViewStyle, imageS if(textStyle) console.warn('Text style will be ignored unless every child of the view is Text node!') } - return [imageStyle && wrapImage(imageStyle), + return [wrapImage(imageStyle), children ] } From 4fd0e5c77415b4af32973d4bf9a1d050946c07f2 Mon Sep 17 00:00:00 2001 From: shangqunfeng Date: Sun, 2 Jun 2024 13:43:49 +0800 Subject: [PATCH 43/45] fix(*): fix code --- .../webpack-plugin/lib/runtime/components/react/mpx-view.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx index c64630c466..c5c48175d7 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx +++ b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx @@ -172,7 +172,7 @@ function wrapImage(imageStyle) { const show = useRef(false) const imageSize = useRef(null) const layoutInfo = useRef(null) - const [_, forceUpdate] = useState({}) + const [_, forceUpdate] = useState({}) // 用于布局变化,图片变化时,重新渲染。 // 预解析 const preImageInfo = preParseImage(imageStyle) @@ -201,6 +201,7 @@ function wrapImage(imageStyle) { } }, [preImageInfo?.src]) + // 避免hook数量不一致引起的报错 if (!preImageInfo) return null if (!sizeList.includes('auto')) { @@ -213,6 +214,8 @@ function wrapImage(imageStyle) { height: layout.height, width: layout.width } + // 布局变化时,要重新的渲染 + // show为useState时,这里无法重新的渲染 if (imageSize.current) { show.current = true forceUpdate({}) From 9f7ffa4e6d75cc99620045e53b6fe913d756f7e3 Mon Sep 17 00:00:00 2001 From: shangqunfeng Date: Tue, 4 Jun 2024 00:12:19 +0800 Subject: [PATCH 44/45] fix(*): view effect. --- .../lib/runtime/components/react/mpx-view.tsx | 77 ++++++++++--------- .../lib/runtime/components/react/utils.ts | 2 +- 2 files changed, 43 insertions(+), 36 deletions(-) diff --git a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx index c5c48175d7..72b5c27dca 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx +++ b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx @@ -60,8 +60,7 @@ const applyHandlers = (handlers: Handler[] , args) => { } const checkNeedLayout = (style) => { - if (!style) return false - const [width, height] = style.sizeList || [] + const [width, height] = style.sizeList return (PERCENT_REGX.test(height) && width === 'auto') || (PERCENT_REGX.test(width) && height === 'auto') } @@ -152,11 +151,9 @@ const imageStyleToProps = (preImageInfo, imageSize, layoutInfo) => { function preParseImage(imageStyle:ExtendedViewStyle) { - if (!imageStyle) return null - const { backgroundImage, backgroundSize = [ "auto" ] } = imageStyle + const { backgroundImage, backgroundSize = [ "auto" ] } = imageStyle || {} const src = parseUrl(backgroundImage) - if (!src) return null let sizeList = backgroundSize.slice() as string [] @@ -169,10 +166,13 @@ function preParseImage(imageStyle:ExtendedViewStyle) { } function wrapImage(imageStyle) { - const show = useRef(false) - const imageSize = useRef(null) + const [show, setShow] = useState(false) + const [, setImageSizeWidth] = useState(null) + const [, setImageSizeHeight] = useState(null) + const [, setLayoutInfoWidth] = useState(null) + const [, setLayoutInfoHeight] = useState(null) + const sizeInfo = useRef(null) const layoutInfo = useRef(null) - const [_, forceUpdate] = useState({}) // 用于布局变化,图片变化时,重新渲染。 // 预解析 const preImageInfo = preParseImage(imageStyle) @@ -180,50 +180,57 @@ function wrapImage(imageStyle) { // 判断是否可挂载onLayout const needLayout = checkNeedLayout(preImageInfo) - const { src, sizeList = [] } = preImageInfo || {} + const { src, sizeList } = preImageInfo useEffect(() => { - if (!src || sizeList.length === 0 || !sizeList.includes('auto')) return + if(!src) { + setShow(false) + sizeInfo.current = null + layoutInfo.current = null + return + } + if (!sizeList.includes('auto')) { + setShow(true) + return + } Image.getSize(src, (width, height) => { - - imageSize.current = {width, height} + sizeInfo.current = { + width, + height + } //1. 当需要绑定onLayout 2. 获取到布局信息 if (!needLayout || layoutInfo.current) { - show.current = true - forceUpdate({}) + setImageSizeWidth(width) + setImageSizeHeight(height) + if(layoutInfo.current) { + setLayoutInfoWidth(layoutInfo.current.width) + setLayoutInfoHeight(layoutInfo.current.height) + } + setShow(true) } }) - return () => { - show.current = false - imageSize.current = null - layoutInfo.current = null - } }, [preImageInfo?.src]) - // 避免hook数量不一致引起的报错 - if (!preImageInfo) return null - - if (!sizeList.includes('auto')) { - show.current = true - } + if (!preImageInfo?.src) return null const onLayout = (res) => { - const layout = res?.nativeEvent?.layout || {} + const {width, height} = res?.nativeEvent?.layout || {} layoutInfo.current = { - height: layout.height, - width: layout.width + width, + height } - // 布局变化时,要重新的渲染 - // show为useState时,这里无法重新的渲染 - if (imageSize.current) { - show.current = true - forceUpdate({}) + if (sizeInfo.current) { + setImageSizeWidth(sizeInfo.current.width) + setImageSizeHeight(sizeInfo.current.height) + setLayoutInfoWidth(width) + setLayoutInfoHeight(height) + setShow(true) } } - + return - {show.current && } + {show && } } diff --git a/packages/webpack-plugin/lib/runtime/components/react/utils.ts b/packages/webpack-plugin/lib/runtime/components/react/utils.ts index 80ad82afb9..fedab764e9 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/utils.ts +++ b/packages/webpack-plugin/lib/runtime/components/react/utils.ts @@ -1,4 +1,4 @@ -import { useEffect, useRef, ReactNode } from 'react' +import { useEffect, useRef } from 'react' import { StyleProp, StyleSheet, TextStyle, ViewStyle } from 'react-native' export const TEXT_STYLE_REGEX = /color|font.*|text.*|letterSpacing|lineHeight|includeFontPadding|writingDirection/ From 15e39f52050a180acb38fb83decbe7a7a9691f34 Mon Sep 17 00:00:00 2001 From: shangqunfeng Date: Tue, 4 Jun 2024 10:15:01 +0800 Subject: [PATCH 45/45] fix(*): ts. --- .../lib/runtime/components/react/mpx-view.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx index 72b5c27dca..9b1933c0f5 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx +++ b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx @@ -4,8 +4,8 @@ * ✔ hover-start-time * ✔ hover-stay-time */ -import { View, Text, ViewStyle, NativeSyntheticEvent, ImageProps, ImageResizeMode, StyleSheet, Image, ImageURISource, ImageStyle } from 'react-native' -import React, { useRef, useState, useEffect, forwardRef, Children, ForwardedRef, ReactNode } from 'react' +import { View, Text, ViewStyle, NativeSyntheticEvent, ImageProps, ImageResizeMode, StyleSheet, Image } from 'react-native' +import React, { useRef, useState, useEffect, forwardRef, Children, ForwardedRef, ReactNode, FunctionComponent, ReactElement } from 'react' // @ts-ignore import useInnerProps from './getInnerListeners' @@ -243,8 +243,8 @@ function splitStyle(styles: ExtendedViewStyle) { }, {}) } -const isText = (ele: ReactNode) => { - const displayName = ele?.type?.displayName +const isText = (ele: ReactElement) => { + const displayName = (ele?.type as FunctionComponent)?.displayName return displayName === 'mpx-text' || displayName === 'Text' } @@ -253,7 +253,7 @@ function every(children: ReactNode, callback: (children: ReactNode) => boolean ) } function wrapChildren(children: ReactNode, textStyle?: ExtendedViewStyle, imageStyle?: ExtendedViewStyle) { - if (every(children, (child)=>isText(child))) { + if (every(children, (child)=>isText(child as ReactElement))) { children = {children} } else { if(textStyle) console.warn('Text style will be ignored unless every child of the view is Text node!')