Skip to content

Commit

Permalink
feat: 抽离layout
Browse files Browse the repository at this point in the history
  • Loading branch information
lareinayanyu committed Oct 17, 2024
1 parent 78a6514 commit 1482211
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 14 deletions.
31 changes: 31 additions & 0 deletions packages/webpack-plugin/lib/runtime/components/react/common.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { TextStyle } from 'react-native'
import { Children, cloneElement } from 'react'
import { VarContext } from './context'
import { isText } from './utils'

export interface WrapChildrenConfig {
hasVarDec: boolean
varContext?: Record<string, any>
}

interface TextConfig {
textStyle?: TextStyle
textProps?: Record<string, any>
}

export function wrapChildren (props: Record<string, any> = {}, { hasVarDec, varContext }: WrapChildrenConfig, { textStyle, textProps } : TextConfig = {}) {
let { children } = props
if (textStyle || textProps) {
children = Children.map(children, (child) => {
if (isText(child)) {
const style = { ...textStyle, ...child.props.style }
return cloneElement(child, { ...textProps, style })
}
return child
})
}
if (hasVarDec && varContext) {
children = <VarContext.Provider value={varContext}>{children}</VarContext.Provider>
}
return children
}
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ export const getCustomEvent = (
const useInnerProps = (
props: Props = {},
additionalProps: AdditionalProps = {},
removeProps: RemoveProps = [],
useRemoveProps: RemoveProps = [],
rawConfig?: UseInnerPropsConfig
) => {
const ref = useRef<InnerRef>({
Expand All @@ -130,6 +130,14 @@ const useInnerProps = (
const propsRef = useRef<Record<string, any>>({})
const eventConfig: { [key: string]: string[] } = {}
const config = rawConfig || { layoutRef: { current: {} }, disableTouch: false, disableTap: false }
const removeProps = [
'enable-var',
'external-var-context',
'parent-font-size',
'parent-width',
'parent-height',
...useRemoveProps
]

propsRef.current = { ...props, ...additionalProps }

Expand Down
51 changes: 39 additions & 12 deletions packages/webpack-plugin/lib/runtime/components/react/mpx-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,14 @@ import { JSX, useRef, forwardRef, ReactNode } from 'react'
import useNodesRef, { HandlerRef } from './useNodesRef'
import useInnerProps, { getCustomEvent } from './getInnerListeners'
import { FormContext } from './context'

import { useTransformStyle, splitProps, splitStyle, useLayout } from './utils'
import { wrapChildren } from './common'
interface FormProps {
style?: Record<string, any>;
children: ReactNode;
'enable-offset'?: boolean;
'enable-var'?: boolean
'external-var-context'?: Record<string, any>
bindsubmit?: (evt: {
detail: {
value: any;
Expand All @@ -22,18 +26,29 @@ interface FormProps {
bindreset?: () => void;
}

const _Form = forwardRef<HandlerRef<View, FormProps>, FormProps>((props: FormProps, ref): JSX.Element => {
const { children, style } = props
const layoutRef = useRef({})
const _Form = forwardRef<HandlerRef<View, FormProps>, FormProps>((fromProps: FormProps, ref): JSX.Element => {
const { textProps, innerProps: props = {} } = splitProps(fromProps)
const formValuesMap = useRef(new Map()).current
const {
style,
'enable-var': enableVar,
'external-var-context': externalVarContext
} = props

const {
hasSelfPercent,
normalStyle,
hasVarDec,
varContextRef,
setWidth,
setHeight
} = useTransformStyle(style, { enableVar, externalVarContext })

const { textStyle, innerStyle } = splitStyle(normalStyle)

const { nodeRef: formRef } = useNodesRef(props, ref)

const onLayout = (e: LayoutChangeEvent) => {
formRef.current?.measure((x: number, y: number, width: number, height: number, offsetLeft: number, offsetTop: number) => {
layoutRef.current = { x, y, width, height, offsetLeft, offsetTop }
})
}
const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: formRef })

const submit = () => {
const { bindsubmit } = props
Expand Down Expand Up @@ -63,9 +78,9 @@ const _Form = forwardRef<HandlerRef<View, FormProps>, FormProps>((props: FormPro
}

const innerProps = useInnerProps(props, {
style: { ...innerStyle, ...layoutStyle },
ref: formRef,
style,
onLayout
...layoutProps
}, [
'children',
'style',
Expand All @@ -78,7 +93,19 @@ const _Form = forwardRef<HandlerRef<View, FormProps>, FormProps>((props: FormPro
{...innerProps}
>
<FormContext.Provider value={{ formValuesMap, submit, reset }}>
{children}
{
wrapChildren(
props,
{
hasVarDec,
varContext: varContextRef.current
},
{
textStyle,
textProps
}
)
}
</FormContext.Provider>
</View>
)
Expand Down
42 changes: 41 additions & 1 deletion packages/webpack-plugin/lib/runtime/components/react/utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useEffect, useRef, ReactNode, ReactElement, FunctionComponent, isValidElement, useContext, useState } from 'react'
import { Dimensions, StyleSheet } from 'react-native'
import { Dimensions, StyleSheet, LayoutChangeEvent } from 'react-native'
import { isObject, hasOwn, diffAndCloneA, error, warn } from '@mpxjs/utils'
import { VarContext } from './context'
import { ExpressionParser, parseFunc, ReplaceSource } from './parser'
Expand All @@ -10,6 +10,9 @@ export const URL_REGEX = /^\s*url\(["']?(.*?)["']?\)\s*$/
export const BACKGROUND_REGEX = /^background(Image|Size|Repeat|Position)$/
export const TEXT_PROPS_REGEX = /ellipsizeMode|numberOfLines/
export const DEFAULT_FONT_SIZE = 16
export const DEFAULT_UNLAY_STYLE = {
opacity: 0
}

export const throwReactWarning = (message: string) => {
setTimeout(() => {
Expand Down Expand Up @@ -439,3 +442,40 @@ export function splitProps<T extends Record<string, any>> (props: T) {
}
})
}

interface layoutConfig {
props: Record<string, any>;
hasSelfPercent: boolean;
setWidth:any
setHeight: any
onLayout?: any
nodeRef: any
}
export const useLayout = ({ props, hasSelfPercent, setWidth, setHeight, onLayout, nodeRef }:layoutConfig) => {
const layoutRef = useRef({})
const hasLayoutRef = useRef(false)
const layoutStyle: Record<string, any> = hasLayoutRef.current ? {} : DEFAULT_UNLAY_STYLE
const layoutProps: Record<string, any> = {}
if (hasSelfPercent || onLayout) {
layoutProps.onLayout = (e: LayoutChangeEvent) => {
hasLayoutRef.current = true
if (hasSelfPercent) {
const { width, height } = e?.nativeEvent?.layout || {}
setWidth(width || 0)
setHeight(height || 0)
}
if (props['enable-offset']) {
nodeRef.current?.measure((x: number, y: number, width: number, height: number, offsetLeft: number, offsetTop: number) => {
layoutRef.current = { x, y, width, height, offsetLeft, offsetTop }
})
}
onLayout && onLayout(e)
props.onLayout && props.onLayout(e)
}
}
return {
layoutRef,
layoutStyle,
layoutProps
}
}

0 comments on commit 1482211

Please sign in to comment.