-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathRenderMain.js
More file actions
136 lines (117 loc) · 4.09 KB
/
RenderMain.js
File metadata and controls
136 lines (117 loc) · 4.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/**
* Copyright (c) 2023 - present TinyEngine Authors.
* Copyright (c) 2023 - present Huawei Cloud Computing Technologies Co., Ltd.
*
* Use of this source code is governed by an MIT-style license.
*
* THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL,
* BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR
* A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS.
*
*/
import { h, provide, nextTick, reactive, shallowReactive, watchEffect, inject } from 'vue'
import _ from 'lodash'
import Loading from './Loading.vue'
import renderer, { parseData } from './render'
import useContext from './useContext'
import { setPageCss } from './pageCss'
import { RENDERER_SETTINGS_KEY } from './renderer-settings'
import useCustomSetting from './useCustomSetting'
export default {
props: {
schema: {
type: Object,
default: () => ({})
}
},
expose: ['setContext', 'getContext', 'setState'],
setup(props) {
const { context, oldSchema, setContext, getContext } = useContext()
const cssScopeId = `data-schema-${Math.random().toString(36).slice(2, 8)}`
const reset = (obj) => {
Object.keys(obj).forEach((key) => delete obj[key])
}
// 设置 customSettings,如 Function
const { setCustomSettings } = useCustomSetting()
const customSettings = inject(RENDERER_SETTINGS_KEY, null)
if (customSettings) {
setCustomSettings(customSettings)
}
const customContext = inject('customContext')
if (customContext) {
setContext({ customContext })
}
provide('pageContext', context)
const pageSchema = reactive({})
const methods = {}
const state = reactive({})
const setMethods = (data = {}, clear) => {
clear && reset(methods)
// 这里有些方法在画布还是有执行的必要的,比如说表格的renderer和formatText方法,包括一些自定义渲染函数
Object.assign(
methods,
Object.fromEntries(
Object.keys(data).map((key) => {
return [key, parseData(data[key], {}, getContext())]
})
)
)
setContext(methods)
}
const setState = (data, clear) => {
clear && reset(state)
if (!pageSchema.state) {
pageSchema.state = data
}
Object.assign(state, parseData(data, {}, getContext()) || {})
}
const setSchema = async (data) => {
if (!data || !Object.keys(data).length) {
return
}
const newSchema = JSON.parse(JSON.stringify(data))
const context = {
state,
cssScopeId
}
// 此处提升很重要,因为setState、initProps也会触发画布重新渲染,所以需要提升上下文环境的设置时间
setContext(context, true)
// 设置方法调用上下文
setMethods(newSchema.methods, true)
// 这里setState(会触发画布渲染),是因为状态管理里面的变量会用到props、utils、bridge、stores、methods
setState(newSchema.state, true)
await nextTick()
setPageCss(data.css, cssScopeId)
Object.assign(pageSchema, newSchema)
}
watchEffect(() => {
// 最后一个判断与上一次的schema做比较,以解决组件循环刷新问题
if (!props.schema || !Object.keys(props.schema) || _.isEqual(props.schema, oldSchema.value)) {
return
}
// 缓存schema
oldSchema.value = _.cloneDeep(props.schema)
setSchema(props.schema)
})
return {
setContext,
getContext,
setState,
pageSchema,
methods,
state
}
},
render() {
// 渲染画布增加根节点,与出码和预览保持一致
const rootChildrenSchema = {
componentName: 'div',
// 手动添加一个唯一的属性,后续在画布选中此节点时方便处理额外的逻辑。由于没有修改schema,不会影响出码
props: {},
children: this.pageSchema.children
}
return this.pageSchema.children?.length
? h(renderer, { schema: rootChildrenSchema, parent: this.pageSchema })
: [h(Loading)]
}
}