Skip to content

Commit

Permalink
fix:修复属性面板-插槽开关切换schema不正确 (#85)
Browse files Browse the repository at this point in the history
  • Loading branch information
yaoyun8 committed Nov 15, 2023
1 parent d13309f commit 1bc4365
Showing 1 changed file with 152 additions and 151 deletions.
303 changes: 152 additions & 151 deletions packages/canvas/src/components/render/render.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import { NODE_UID as DESIGN_UIDKEY, NODE_TAG as DESIGN_TAGKEY, NODE_LOOP as DESI

const { BROADCAST_CHANNEL } = constants
const { hyphenateRE } = utils
const customElements = {}

const transformJSX = (code) =>
transformSync(code, {
Expand All @@ -41,7 +42,7 @@ const transformJSX = (code) =>
babelPluginJSX,
{
pragma: 'h',
isCustomElement: (name) => custElements[name]
isCustomElement: (name) => customElements[name]
}
]
]
Expand Down Expand Up @@ -131,15 +132,10 @@ const isObject = (data) => {
export const isStateAccessor = (stateData) =>
stateData?.accessor?.getter?.type === 'JSFunction' || stateData?.accessor?.setter?.type === 'JSFunction'

const parseI18n = (i18n, scope, ctx) => {
return parseExpression(
{
type: 'JSExpression',
value: `this.i18n('${i18n.key}')`
},
scope,
{ i18n: i18nHost.global.t, ...ctx }
)
// 规避创建function eslint报错
export const newFn = (...argv) => {
const Fn = Function
return new Fn(...argv)
}

const parseExpression = (data, scope, ctx) => {
Expand All @@ -160,6 +156,26 @@ const parseExpression = (data, scope, ctx) => {
}
}

const parseI18n = (i18n, scope, ctx) => {
return parseExpression(
{
type: 'JSExpression',
value: `this.i18n('${i18n.key}')`
},
scope,
{ i18n: i18nHost.global.t, ...ctx }
)
}

const renderDefault = (children, scope, parent) =>
children.map?.((child) =>
h(renderer, {
schema: child,
scope,
parent
})
)

const parseJSSlot = (data, scope) => {
return ($scope) => renderDefault(data.value, { ...scope, ...$scope }, data)
}
Expand Down Expand Up @@ -225,10 +241,105 @@ const parseFunctionString = (fnStr) => {
return null
}

// 规避创建function eslint报错
export const newFn = (...argv) => {
const Fn = Function
return new Fn(...argv)
const getPlainProps = (object = {}) => {
const { slot, ...rest } = object
const props = {}

if (slot) {
rest.slot = slot.name || slot
}

Object.entries(rest).forEach(([key, value]) => {
let renderKey = key

// html 标签属性会忽略大小写,所以传递包含大写的 props 需要转换为 kebab 形式的 props
if (!/on[A-Z]/.test(renderKey) && hyphenateRE.test(renderKey)) {
renderKey = hyphenate(renderKey)
}

if (['boolean', 'string', 'number'].includes(typeof value)) {
props[renderKey] = value
} else {
// 如果传给webcomponent标签的是对象或者数组需要使用.prop修饰符,转化成h函数就是如下写法
props[`.${renderKey}`] = value
}
})
return props
}

const generateCollection = (schema) => {
if (schema.componentName === 'Collection' && schema.props?.dataSource && schema.children) {
schema.children.forEach((item) => {
const fetchData = item.props?.fetchData
const methodMatch = fetchData?.value?.match(/this\.(.+?)}/)
if (fetchData && methodMatch?.[1]) {
const methodName = methodMatch[1].trim()
// 缓存表格fetchData对应的数据源信息
collectionMethodsMap[methodName] = schema.props.dataSource
}
})
}
}

const generateBlockContent = (schema) => {
if (schema?.componentName === 'Collection') {
generateCollection(schema)
}
if (Array.isArray(schema?.children)) {
schema.children.forEach((item) => {
generateBlockContent(item)
})
}
}

const registerBlock = (componentName) => {
getController()
.registerBlock?.(componentName)
.then((res) => {
const blockSchema = res.content

// 拿到区块数据,建立区块中数据源的映射关系
generateBlockContent(blockSchema)

// 如果区块的根节点有百分比高度,则需要特殊处理,把高度百分比传递下去,适配大屏应用
if (/height:\s*?[\d|.]+?%/.test(blockSchema?.props?.style)) {
const blockDoms = document.querySelectorAll(hyphenate(componentName))
blockDoms.forEach((item) => {
item.style.height = '100%'
})
}
})
}

export const wrapCustomElement = (componentName) => {
const material = getController().getMaterial(componentName)

if (!Object.keys(material).length) {
registerBlock(componentName)
}

customElements[componentName] = {
name: componentName + '.ce',
render() {
return h(
hyphenate(componentName),
window.parent.TinyGlobalConfig.dslMode === 'Vue' ? getPlainProps(this.$attrs) : this.$attrs,
this.$slots.default?.()
)
}
}

return customElements[componentName]
}

export const getComponent = (name) => {
return (
Mapper[name] ||
getNative(name) ||
getBlock(name) ||
customElements[name] ||
(isHTMLTag(name) ? name : wrapCustomElement(name))
)
}

// 解析JSX字符串为可执行函数
Expand Down Expand Up @@ -297,6 +408,8 @@ const parseLoopArgs = (_loop) => {
return undefined
}

export const getIcon = (name) => window.TinyVueIcon?.[name]?.() || ''

const parseObjectData = (data, scope, ctx) => {
if (!data) {
return data
Expand Down Expand Up @@ -382,124 +495,33 @@ const stopEvent = (event) => {
return false
}

const getPlainProps = (object = {}) => {
const { slot, ...rest } = object
const props = {}

if (slot) {
rest.slot = slot.name || slot
}

Object.entries(rest).forEach(([key, value]) => {
let renderKey = key

// html 标签属性会忽略大小写,所以传递包含大写的 props 需要转换为 kebab 形式的 props
if (!/on[A-Z]/.test(renderKey) && hyphenateRE.test(renderKey)) {
renderKey = hyphenate(renderKey)
}

if (['boolean', 'string', 'number'].includes(typeof value)) {
props[renderKey] = value
} else {
// 如果传给webcomponent标签的是对象或者数组需要使用.prop修饰符,转化成h函数就是如下写法
props[`.${renderKey}`] = value
}
})
return props
}

const custElements = {}

const generateCollection = (schema) => {
if (schema.componentName === 'Collection' && schema.props?.dataSource && schema.children) {
schema.children.forEach((item) => {
const fetchData = item.props?.fetchData
const methodMatch = fetchData?.value?.match(/this\.(.+?)}/)
if (fetchData && methodMatch?.[1]) {
const methodName = methodMatch[1].trim()
// 缓存表格fetchData对应的数据源信息
collectionMethodsMap[methodName] = schema.props.dataSource
}
})
}
}

const generateBlockContent = (schema) => {
if (schema?.componentName === 'Collection') {
generateCollection(schema)
}
if (Array.isArray(schema?.children)) {
schema.children.forEach((item) => {
generateBlockContent(item)
})
}
}

const registerBlock = (componentName) => {
getController()
.registerBlock?.(componentName)
.then((res) => {
const blockSchema = res.content

// 拿到区块数据,建立区块中数据源的映射关系
generateBlockContent(blockSchema)

// 如果区块的根节点有百分比高度,则需要特殊处理,把高度百分比传递下去,适配大屏应用
if (/height:\s*?[\d|.]+?%/.test(blockSchema?.props?.style)) {
const blockDoms = document.querySelectorAll(hyphenate(componentName))
blockDoms.forEach((item) => {
item.style.height = '100%'
})
}
})
}

export const wrapCustomElement = (componentName) => {
const material = getController().getMaterial(componentName)

if (!Object.keys(material).length) {
registerBlock(componentName)
}

custElements[componentName] = {
name: componentName + '.ce',
render() {
return h(
hyphenate(componentName),
window.parent.TinyGlobalConfig.dslMode === 'Vue' ? getPlainProps(this.$attrs) : this.$attrs,
this.$slots.default?.()
)
}
}

return custElements[componentName]
}

const goupSlot = (children, isCustElm) => {
const slotGrup = {}
const generateSlotGroup = (children, isCustomElm) => {
const slotGroup = {}

children.forEach((child) => {
const { componentName, children, params = [], props } = child
const slot = child.slot || props?.slot || 'default'
const slot = child.slot || props?.slot?.name || props?.slot || 'default'

isCustElm && (child.props.slot = 'slot') // CE下需要给子节点加上slot标识
slotGrup[slot] = slotGrup[slot] || {
isCustomElm && (child.props.slot = 'slot') // CE下需要给子节点加上slot标识
slotGroup[slot] = slotGroup[slot] || {
value: [],
params
}
slotGrup[slot].value.push(...(componentName === 'Template' ? children : [child])) // template 标签直接过滤掉

slotGroup[slot].value.push(...(componentName === 'Template' && children.length ? children : [child])) // template 标签直接过滤掉
})

return slotGrup
return slotGroup
}

const renderSlot = (children, scope, schema, isCustElm) => {
const renderSlot = (children, scope, schema, isCustomElm) => {
if (children.some((a) => a.componentName === 'Template')) {
const slotGrup = goupSlot(children, isCustElm)
const slotGroup = generateSlotGroup(children, isCustomElm)
const slots = {}

Object.keys(slotGrup).forEach((slotName) => {
slots[slotName] = ($scope) => renderDefault(slotGrup[slotName].value, { ...scope, ...$scope }, schema)
Object.keys(slotGroup).forEach((slotName) => {
slots[slotName] = ($scope) => renderDefault(slotGroup[slotName].value, { ...scope, ...$scope }, schema)
})

return slots
Expand All @@ -508,18 +530,6 @@ const renderSlot = (children, scope, schema, isCustElm) => {
return { default: () => renderDefault(children, scope, schema) }
}

export const getComponent = (name) => {
return (
Mapper[name] ||
getNative(name) ||
getBlock(name) ||
custElements[name] ||
(isHTMLTag(name) ? name : wrapCustomElement(name))
)
}

export const getIcon = (name) => window.TinyVueIcon?.[name]?.() || ''

const checkGroup = (componentName) => configure[componentName]?.nestingRule?.childWhitelist?.length

const clickCapture = (componentName) => configure[componentName]?.clickCapture !== false
Expand Down Expand Up @@ -561,14 +571,16 @@ const getBindProps = (schema, scope) => {
return bindProps
}

const renderDefault = (children, scope, parent) =>
children.map?.((child) =>
h(renderer, {
schema: child,
scope,
parent
})
)
const getLoopScope = ({ scope, index, item, loopArgs }) => {
return {
...scope,
...(parseLoopArgs({
item,
index,
loopArgs
}) || {})
}
}

const renderGroup = (children, scope, parent) => {
return children.map?.((schema) => {
Expand Down Expand Up @@ -600,29 +612,18 @@ const renderGroup = (children, scope, parent) => {
})
}

const getLoopScope = ({ scope, index, item, loopArgs }) => {
return {
...scope,
...(parseLoopArgs({
item,
index,
loopArgs
}) || {})
}
}

const getChildren = (schema, mergeScope) => {
const { componentName, children } = schema

const isNative = typeof component === 'string'
const isCustElm = custElements[componentName]
const isCustomElm = customElements[componentName]
const isGroup = checkGroup(componentName)

if (Array.isArray(children)) {
if (isNative || isCustElm) {
if (isNative || isCustomElm) {
return renderDefault(children, mergeScope, schema)
} else {
return isGroup ? renderGroup(children, mergeScope, schema) : renderSlot(children, mergeScope, schema, isCustElm)
return isGroup ? renderGroup(children, mergeScope, schema) : renderSlot(children, mergeScope, schema, isCustomElm)
}
} else {
return parseData(children, mergeScope)
Expand Down

0 comments on commit 1bc4365

Please sign in to comment.