/** * MyBricks Opensource * https://mybricks.world * This source code is licensed under the MIT license. * * CheMingjun @2019 * mybricks@126.com */ import React, { memo, useEffect, useMemo, useState } from "react"; import { View } from '@tarojs/components'; import { isNumber, uuid } from "./utils"; // import css from "./RenderSlot.less"; import ErrorBoundary from "./ErrorBoundary"; import { observer } from './observable' const css = {}; export default function RenderSlot({ scope, slot, params, inputs, outputs, _inputs, _outputs, wrapper, template, env, getComDef, getContext, __rxui_child__, onError, logger }) { const { style, comAry } = slot const itemAry = [] comAry.forEach((com, index) => {//组件逐个渲染 const { id, def }: Com = com const comDef = getComDef(def) if (comDef) { const props = getContext(id, scope, { inputs, outputs, _inputs, _outputs }) itemAry.push({ id, jsx: , inputs: props.inputsCallable, style: props.style }) } else { const jsx = ( 组件 (namespace = {def.namespace})未找到. ) itemAry.push({ id, jsx }) } }) if (typeof wrapper === 'function') { return wrapper(itemAry) } else { const paramsStyle = params?.style; const slotStyle = paramsStyle || style; return ( {itemAry.map((item, index) => { return item.jsx; })} ) } } const RenderCom = observer(function ({ com, props, scope, template, env, getComDef, getContext, __rxui_child__, onError, logger }) { const { id, def, slots = {} }: Com = com const { data, style, inputs: myInputs, outputs: myOutputs, _inputs: _myInputs, _outputs: _myOutputs } = props console.error(style, "renderslot style") const comDef = getComDef(def) const slotsProxy = new Proxy(slots, { get(target, slotId: string) { const props = getContext(id, slotId) const errorStringPrefix = `组件(namespace=${def.namespace})的插槽(id=${slotId})` if (!props) { throw new Error(`${errorStringPrefix} 获取context失败.`) } return { render(params: { key, inputValues, inputs, outputs, _inputs, _outputs, wrap, itemWrap, style }) { const slot = slots[slotId] if (slot) { return } else { return ( {errorStringPrefix} 未找到. ) } }, _inputs: props._inputs, inputs: props.inputs, outputs: props.outputs } } }) const parentSlot = useMemo(() => { if (props.frameId && props.parentComId) { const slotProps = getContext(props.parentComId, props.frameId, scope?.parent) if (slotProps) { return { get _inputs() { return new Proxy({}, { get(target, name) { const fn = slotProps._inputRegs[name] return fn } }) } } } } }, []) const classes = getClasses({ style }) const sizeStyle = getSizeStyle({ style }) const marginStyle = getMarginStyle({ style }) const otherStyle: any = {} if (['fixed', 'absolute'].includes(style.position)) { if (style.position === "fixed" && style.fixedY === "bottom") { otherStyle.bottom = style.bottom; } else if (style.top) { otherStyle.top = style.top; } if (style.position === "fixed" && style.fixedX === "right") { otherStyle.right = style.right; } else if (style.left) { otherStyle.left = style.left; } otherStyle.zIndex = 1000; } let jsx = ( { }} parentSlot={parentSlot} __rxui_child__={__rxui_child__} onError={onError} logger={logger} /> ) if (typeof template === 'function') { jsx = template({ id, jsx }) } // console.error(rawToProxy, "==============rawToProxy=============="); // console.error(proxyToRaw, "==============proxyToRaw=============="); // console.error(rawToProxy.get(style)); // console.error(proxyToRaw.get(style)); // const [_r, _setR] = useState(style.display); // console.warn(style, "style"); // console.warn(isProxy(style), "isProxy"); // setInterval(()=>{ // // console.warn(style.display); // _setR(style.display); // }, 500); // setTimeout(() => { // console.warn("setTimeout"); // _setR(Math.random()); // }, 2000); jsx = ( {jsx} ) return jsx }) const SlotRender = memo(({ slotId, props, slot, params, scope, env, style, getComDef, getContext, onError, logger, __rxui_child__ }) => { console.log("执行 SlotRender") let curScope if (params) { let nowScopeId = uuid() curScope = { id: nowScopeId, frameId: slotId } if (scope) { curScope.parent = scope } } else { curScope = scope } props.run(curScope)//传递scope let wrapFn if (params) { const ivs = params.inputValues if (typeof ivs === 'object') { //requestAnimationFrame(() => { for (let pro in ivs) { props.inputs[pro](ivs[pro], curScope) } //}) } if (typeof params.wrap === 'function') { wrapFn = params.wrap } //}) } return ( //
//
) }, (prevProps, nextProps) => { if (prevProps.params?.key !== nextProps?.params?.key) {//key 不同才刷新 return false } return true }) //----------------------------------------------------------------------- function calSlotStyles(style, hasParamsStyle) { // 兼容旧的style const { paddingLeft, paddingTop, paddingRight, paddingBottom, background, ...otherStyle } = style; let slotStyle = { paddingLeft: paddingLeft || 0, paddingTop: paddingTop || 0, paddingRight: paddingRight || 0, paddingBottom: paddingBottom || 0, //height: style.customHeight || '100%' } as any // 兼容旧的style const isOldBackground = typeof background === 'object' if (isOldBackground) { const { background: bg, backgroundImage, backgroundColor, backgroundRepeat, backgroundSize } = background; slotStyle.backgroundRepeat = backgroundRepeat slotStyle.backgroundSize = backgroundSize if (bg) { slotStyle.background = bg } else { slotStyle.backgroundImage = backgroundImage slotStyle.backgroundColor = backgroundColor } } else { slotStyle.background = background } if (hasParamsStyle) { slotStyle = Object.assign(slotStyle, otherStyle) } return slotStyle } function calSlotClasses(slotStyle) { const rtn = [css.slot] const style = slotStyle if (style) { if (style.layout?.toLowerCase() == 'flex-column') { rtn.push(css.lyFlexColumn) } else if (style.layout?.toLowerCase() == 'flex-row') { rtn.push(css.lyFlexRow) } const justifyContent = style.justifyContent if (justifyContent) { if (justifyContent.toUpperCase() === 'FLEX-START') { rtn.push(css.justifyContentFlexStart) } else if (justifyContent.toUpperCase() === 'CENTER') { rtn.push(css.justifyContentFlexCenter) } else if (justifyContent.toUpperCase() === 'FLEX-END') { rtn.push(css.justifyContentFlexFlexEnd) } else if (justifyContent.toUpperCase() === 'SPACE-AROUND') { rtn.push(css.justifyContentFlexSpaceAround) } else if (justifyContent.toUpperCase() === 'SPACE-BETWEEN') { rtn.push(css.justifyContentFlexSpaceBetween) } } const alignItems = style.alignItems if (alignItems) { if (alignItems.toUpperCase() === 'FLEX-START') { rtn.push(css.alignItemsFlexStart) } else if (alignItems.toUpperCase() === 'CENTER') { rtn.push(css.alignItemsFlexCenter) } else if (alignItems.toUpperCase() === 'FLEX-END') { rtn.push(css.alignItemsFlexFlexEnd) } } } return rtn.join(' ') } function getClasses({ style }) { const classes = [css.com] if (style.flex === 1) { classes.push(css.flex) } return classes.join(" ") } function getSizeStyle({ style }) { const sizeStyle: any = {} const { width, height } = style if (!width) { sizeStyle.width = "100%" } else if (isNumber(width)) { sizeStyle.width = width + "px" } else if (width) { sizeStyle.width = width } if (isNumber(height)) { sizeStyle.height = height + "px" } else if (height) { sizeStyle.height = height } return sizeStyle } function getMarginStyle({ style }) { const marginStyle: any = {} const { width, marginTop, marginLeft, marginRight, marginBottom } = style if (isNumber(marginTop)) { marginStyle.marginTop = marginTop + "px" } if (isNumber(marginLeft)) { if (typeof width === "number" || marginLeft < 0) { marginStyle.marginLeft = marginLeft + "px" } else { marginStyle.paddingLeft = marginLeft + "px" } } if (isNumber(marginRight)) { if (typeof width === "number" || marginRight < 0) { marginStyle.marginRight = marginRight + "px" } else { marginStyle.paddingRight = marginRight + "px" } } if (isNumber(marginBottom)) { marginStyle.marginBottom = marginBottom + "px" } return marginStyle }