resolver-egretimp-plus 0.1.124 → 0.1.126
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/h5/index.js +18 -18
- package/dist/web/index.js +2 -2
- package/package.json +1 -1
- package/src/analysisComponent.jsx +0 -1
- package/src/components/lazyLoadComponent/index.js +1 -0
- package/src/components/lazyLoadComponent/src/LazyLoadComponent.jsx +137 -0
- package/src/components/lazyLoadComponent/src/LazyLoadComponent.scss +36 -0
- package/src/components/packages-web/CustomComponentPlain.vue +3 -2
- package/src/components/packages-web/CustomComponentTabs.vue +1 -5
- package/src/components/packages-web/ElDatePicker.vue +24 -8
- package/src/hooks/pageConfig.js +11 -1
- package/src/index.jsx +29 -3
- package/src/resolver-web.vue +3 -1
- package/src/utils/common.js +1 -0
- package/src/utils/lazyLoad.js +69 -0
- package/src/utils/render.jsx +173 -32
- package/src/utils/validateByData.js +177 -0
package/package.json
CHANGED
|
@@ -235,7 +235,6 @@ export default {
|
|
|
235
235
|
*/
|
|
236
236
|
const parent = inject('parent', null)
|
|
237
237
|
const dynamicMapComp = inject('dynamicMapComp')
|
|
238
|
-
|
|
239
238
|
const configLinks = [parent, ...props.additionConfigs, props.config]
|
|
240
239
|
configLinks.reduce((parent, config) => {
|
|
241
240
|
definePrivatelyProp(config, 'parent', parent)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {default as default} from './src/LazyLoadComponent'
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { onMounted, onUnmounted, reactive, ref, TransitionGroup } from "vue"
|
|
2
|
+
import './LazyLoadComponent.scss'
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
name: 'LazyLoadComponent',
|
|
6
|
+
props: {
|
|
7
|
+
timeout: {
|
|
8
|
+
type: Number
|
|
9
|
+
},
|
|
10
|
+
tagName: {
|
|
11
|
+
type: String,
|
|
12
|
+
default: 'div'
|
|
13
|
+
},
|
|
14
|
+
viewport: {
|
|
15
|
+
type: typeof window !== 'undefined' ? window.HTMLElement : Object,
|
|
16
|
+
default: () => null
|
|
17
|
+
},
|
|
18
|
+
threshold: {
|
|
19
|
+
type: String,
|
|
20
|
+
default: '0px'
|
|
21
|
+
},
|
|
22
|
+
direction: {
|
|
23
|
+
type: String,
|
|
24
|
+
default: 'vertical'
|
|
25
|
+
},
|
|
26
|
+
maxWaitingTime: {
|
|
27
|
+
type: Number,
|
|
28
|
+
default: 50
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
setup(props, { slots, emit }) {
|
|
32
|
+
const el = ref(null)
|
|
33
|
+
let timer = null
|
|
34
|
+
let io = null
|
|
35
|
+
const data = reactive({
|
|
36
|
+
isInit: false,
|
|
37
|
+
timer: null,
|
|
38
|
+
io: null,
|
|
39
|
+
loading: false
|
|
40
|
+
})
|
|
41
|
+
// 如果指定timeout则无论可见与否都是在timeout之后初始化
|
|
42
|
+
if (props.timeout) {
|
|
43
|
+
timer = setTimeout(() => {
|
|
44
|
+
toInit()
|
|
45
|
+
}, props.timeout)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function intersectionHandler (entries) {
|
|
49
|
+
if (
|
|
50
|
+
// 正在交叉
|
|
51
|
+
entries[0].isIntersecting ||
|
|
52
|
+
// 交叉率大于0
|
|
53
|
+
entries[0].intersectionRatio
|
|
54
|
+
) {
|
|
55
|
+
toInit()
|
|
56
|
+
io?.unobserve(el.value)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function requestAnimationFrame (callback) {
|
|
61
|
+
// 防止等待太久没有执行回调
|
|
62
|
+
// 设置最大等待时间
|
|
63
|
+
setTimeout(() => {
|
|
64
|
+
if (data.isInit) return
|
|
65
|
+
callback()
|
|
66
|
+
}, props.maxWaitingTime)
|
|
67
|
+
|
|
68
|
+
// 兼容不支持requestAnimationFrame 的浏览器
|
|
69
|
+
return (window.requestAnimationFrame || ((callback) => setTimeout(callback, 1000 / 60)))(callback)
|
|
70
|
+
}
|
|
71
|
+
// 处理组件和骨架组件的切换
|
|
72
|
+
function toInit () {
|
|
73
|
+
debugger
|
|
74
|
+
// 此时说明骨架组件即将被切换
|
|
75
|
+
emit('beforeInit')
|
|
76
|
+
|
|
77
|
+
// 此时可以准备加载懒加载组件的资源
|
|
78
|
+
data.loading = true
|
|
79
|
+
|
|
80
|
+
// 由于函数会在主线程中执行,加载懒加载组件非常耗时,容易卡顿
|
|
81
|
+
// 所以在requestAnimationFrame回调中延后执行
|
|
82
|
+
requestAnimationFrame(() => {
|
|
83
|
+
data.isInit = true
|
|
84
|
+
emit('init')
|
|
85
|
+
})
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
onMounted(() => {
|
|
89
|
+
if (!props.timeout) {
|
|
90
|
+
// 根据滚动方向来构造视口外边距,用于提前加载
|
|
91
|
+
let rootMargin
|
|
92
|
+
switch (props.direction) {
|
|
93
|
+
case 'vertical':
|
|
94
|
+
rootMargin = `${props.threshold} 0px`
|
|
95
|
+
break
|
|
96
|
+
case 'horizontal':
|
|
97
|
+
rootMargin = `0px ${props.threshold}`
|
|
98
|
+
break
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
try {
|
|
102
|
+
// 观察视口与组件容器的交叉情况
|
|
103
|
+
io = new window.IntersectionObserver(intersectionHandler, {
|
|
104
|
+
rootMargin,
|
|
105
|
+
root: props.viewport,
|
|
106
|
+
threshold: [0, Number.MIN_VALUE, 0.01]
|
|
107
|
+
});
|
|
108
|
+
io.observe(el.value);
|
|
109
|
+
} catch (e) {
|
|
110
|
+
toInit()
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
})
|
|
114
|
+
onUnmounted(() => {
|
|
115
|
+
if (io) {
|
|
116
|
+
io.unobserve(el.value)
|
|
117
|
+
}
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
return () => (
|
|
121
|
+
<TransitionGroup ref={(e) => {el.value= e.$el}} tag={props.tagName} name="lazy-component" className="lazy-load-component"
|
|
122
|
+
onBeforeEnter={(el) => emit('before-enter', el)}
|
|
123
|
+
onBbeforeLeave={(el) => emit('before-leave', el)}
|
|
124
|
+
onAfterEnter={(el) => emit('after-enter', el)}
|
|
125
|
+
onAfterLeave={(el) => emit('after-leave', el)}
|
|
126
|
+
>
|
|
127
|
+
{
|
|
128
|
+
data.isInit ?
|
|
129
|
+
slots?.default(data.loading) :
|
|
130
|
+
slots?.skeleton ?
|
|
131
|
+
slots?.skeleton() :
|
|
132
|
+
null
|
|
133
|
+
}
|
|
134
|
+
</TransitionGroup>
|
|
135
|
+
)
|
|
136
|
+
}
|
|
137
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
.lazy-load-component {
|
|
2
|
+
position: relative;
|
|
3
|
+
width: 100%;
|
|
4
|
+
}
|
|
5
|
+
.CustomComponentRow {
|
|
6
|
+
& > .lazy-load-component {
|
|
7
|
+
width: unset;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.lazy-component-enter {
|
|
12
|
+
opacity: 0;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.lazy-component-enter-to {
|
|
16
|
+
opacity: 1;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.lazy-component-enter-active {
|
|
20
|
+
transition: opacity 0.3s 0.2s;
|
|
21
|
+
position: absolute;
|
|
22
|
+
top: 0;
|
|
23
|
+
width: 100%;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.lazy-component-leave {
|
|
27
|
+
opacity: 1;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.lazy-component-leave-to {
|
|
31
|
+
opacity: 0;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.lazy-component-leave-active {
|
|
35
|
+
transition: opacity 0.5s;
|
|
36
|
+
}
|
|
@@ -7,14 +7,14 @@ import { commonPropsType, PLAIN_TYPE_OPTIONS_COLUMNS } from '../../utils/const'
|
|
|
7
7
|
import { computed, defineModel, defineProps, inject, getCurrentInstance, watch, nextTick, useAttrs } from 'vue'
|
|
8
8
|
import dayjs from 'dayjs'
|
|
9
9
|
import { isNaN } from '../../utils/is';
|
|
10
|
-
import { useFormItem } from 'element-plus'
|
|
11
10
|
|
|
11
|
+
const useFormItem = inject('_useFormItem', null)
|
|
12
12
|
defineOptions({
|
|
13
13
|
inheritAttrs: false
|
|
14
14
|
})
|
|
15
15
|
|
|
16
16
|
const attrs = useAttrs()
|
|
17
|
-
const { formItem: elFormItem } = useFormItem()
|
|
17
|
+
const { formItem: elFormItem } = useFormItem?.() || {}
|
|
18
18
|
const modelValue = defineModel()
|
|
19
19
|
const props = defineProps({
|
|
20
20
|
...commonPropsType,
|
|
@@ -230,6 +230,7 @@ function formatValue(value) {
|
|
|
230
230
|
: formatted
|
|
231
231
|
}
|
|
232
232
|
|
|
233
|
+
|
|
233
234
|
watch(modelValue, () => {
|
|
234
235
|
nextTick(() => {
|
|
235
236
|
elFormItem?.validate?.('blur').catch()
|
|
@@ -11,10 +11,9 @@ import { ElTabs } from 'element-plus'
|
|
|
11
11
|
import Tabs from '../tabs'
|
|
12
12
|
import Renderer from '../../renderer.jsx'
|
|
13
13
|
import { computed, useAttrs, useSlots } from 'vue'
|
|
14
|
-
import { commonPropsType, hasOwn } from '../../utils/index.js'
|
|
14
|
+
import { assertMetaType, commonPropsType, hasOwn } from '../../utils/index.js'
|
|
15
15
|
import { watch } from 'vue'
|
|
16
16
|
import { OPEN_DATA_RULES } from '../../config.js'
|
|
17
|
-
|
|
18
17
|
// import * as lib from 'element-plus/es/utils/index.mjs'
|
|
19
18
|
|
|
20
19
|
const slots = useSlots()
|
|
@@ -127,9 +126,6 @@ if (OPEN_DATA_RULES) {
|
|
|
127
126
|
})
|
|
128
127
|
}
|
|
129
128
|
|
|
130
|
-
function assertMetaType(config, metaType) {
|
|
131
|
-
return config.renderby === metaType || config.metaType === metaType
|
|
132
|
-
}
|
|
133
129
|
|
|
134
130
|
defineExpose({
|
|
135
131
|
setActiveTab(tabMetaCode) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<ElDatePicker v-bind="{ ...attrs, ...
|
|
2
|
+
<ElDatePicker v-bind="{ ...attrs, ...normalDatePickerProps}" :disabledDate="disabledDate" v-model="value">
|
|
3
3
|
<template v-for="(_, key) in slots" :key="key" v-slot:[key]="scope">
|
|
4
4
|
<slot :name="key" v-bind="scope"></slot>
|
|
5
5
|
</template>
|
|
@@ -46,22 +46,38 @@ const datePickerProps = computed(() => {
|
|
|
46
46
|
}
|
|
47
47
|
return ret
|
|
48
48
|
})
|
|
49
|
+
const normalDatePickerProps = computed(() => {
|
|
50
|
+
const ret = {
|
|
51
|
+
...datePickerProps.value
|
|
52
|
+
}
|
|
53
|
+
delete ret.valueFormat
|
|
54
|
+
return ret
|
|
55
|
+
})
|
|
56
|
+
|
|
49
57
|
const attrs = useAttrs()
|
|
50
58
|
const modeValue = defineModel()
|
|
51
59
|
|
|
52
60
|
const value = computed({
|
|
53
61
|
get() {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
62
|
+
let ret = modeValue.value
|
|
63
|
+
if (!isNaN(Number(modeValue.value))) {
|
|
64
|
+
if (
|
|
65
|
+
datePickerProps.value.valueFormat === 'x' ||
|
|
66
|
+
datePickerProps.value.valueFormat === 'timestamp' ||
|
|
67
|
+
`${modeValue.value}`.length >= 13
|
|
68
|
+
) {
|
|
69
|
+
ret = Number(modeValue.value)
|
|
59
70
|
}
|
|
60
|
-
return modeValue.value
|
|
61
71
|
}
|
|
72
|
+
ret = dayjs(ret).toDate()
|
|
73
|
+
return ret
|
|
62
74
|
},
|
|
63
75
|
set(val) {
|
|
64
|
-
|
|
76
|
+
let valueFormat = datePickerProps.value?.valueFormat
|
|
77
|
+
if (valueFormat === 'timestamp') {
|
|
78
|
+
valueFormat = 'x'
|
|
79
|
+
}
|
|
80
|
+
modeValue.value = dayjs(val).format(valueFormat)
|
|
65
81
|
}
|
|
66
82
|
})
|
|
67
83
|
watch(value, () => {
|
package/src/hooks/pageConfig.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { generateFormConfig, parsePageConfig } from "../utils"
|
|
1
|
+
import { generateFormConfig, parsePageConfig } from "../utils/index.js"
|
|
2
2
|
import { ref } from 'vue'
|
|
3
3
|
import { buildInRequest } from "../utils/request"
|
|
4
4
|
import { GET_SYS_PARAM_CACHE, QUERY_PAGE_CONFIG_DATA } from "../api/builtIn"
|
|
@@ -11,6 +11,11 @@ export function usePageConfig() {
|
|
|
11
11
|
const hireRelatMapRulesRef = ref(null)
|
|
12
12
|
const mapCompRef = ref(null)
|
|
13
13
|
function initPageConfig({
|
|
14
|
+
components,
|
|
15
|
+
confirmInstance,
|
|
16
|
+
openChildDialogInstance,
|
|
17
|
+
buttonActions,
|
|
18
|
+
builtPolyfillReq,
|
|
14
19
|
requestTraceId,
|
|
15
20
|
dialogReq,
|
|
16
21
|
mode,
|
|
@@ -30,6 +35,11 @@ export function usePageConfig() {
|
|
|
30
35
|
messageCb
|
|
31
36
|
}) {
|
|
32
37
|
const { pageConfig, mapComp, hireRelatMapRules } = parsePageConfig({
|
|
38
|
+
components,
|
|
39
|
+
confirmInstance,
|
|
40
|
+
openChildDialogInstance,
|
|
41
|
+
buttonActions,
|
|
42
|
+
builtPolyfillReq,
|
|
33
43
|
requestTraceId,
|
|
34
44
|
dialogReq,
|
|
35
45
|
mode,
|
package/src/index.jsx
CHANGED
|
@@ -3,6 +3,7 @@ import Renderer from './renderer.jsx'
|
|
|
3
3
|
// import './style/index.scss'
|
|
4
4
|
import { usePageConfig } from './hooks/pageConfig'
|
|
5
5
|
import { toValidate } from './utils/valid.js'
|
|
6
|
+
import { toValidate as validateByData } from './utils/validateByData.js'
|
|
6
7
|
import { MODE } from "./utils/const.js"
|
|
7
8
|
import { generateRequester } from "./utils/request.js"
|
|
8
9
|
import { executeLoadServices, resetConfigEventInit } from "./components/helper/resolver.js"
|
|
@@ -207,6 +208,7 @@ export default {
|
|
|
207
208
|
},
|
|
208
209
|
emits: ['update:modelValue', 'rootStoreChange'],
|
|
209
210
|
setup(props, { emit, attrs, expose }) {
|
|
211
|
+
const componentsRef = toRef(props, 'components')
|
|
210
212
|
const configsSet = new Set()
|
|
211
213
|
const dynamicMapComp = reactive({})
|
|
212
214
|
const instance = getCurrentInstance()
|
|
@@ -298,6 +300,11 @@ export default {
|
|
|
298
300
|
)
|
|
299
301
|
}
|
|
300
302
|
initPageConfig({
|
|
303
|
+
components: props.components,
|
|
304
|
+
confirmInstance: props.confirmInstance,
|
|
305
|
+
openChildDialogInstance: props.openChildDialogInstance,
|
|
306
|
+
buttonActions: props.buttonActions,
|
|
307
|
+
builtPolyfillReq: props.builtPolyfillReq,
|
|
301
308
|
requestTraceId: props.requestTraceId,
|
|
302
309
|
dialogReq: props.dialogReq,
|
|
303
310
|
mode: props.mode,
|
|
@@ -320,6 +327,11 @@ export default {
|
|
|
320
327
|
|
|
321
328
|
watch(toRef(props, 'config'), () => {
|
|
322
329
|
initPageConfig({
|
|
330
|
+
components: props.components,
|
|
331
|
+
confirmInstance: props.confirmInstance,
|
|
332
|
+
openChildDialogInstance: props.openChildDialogInstance,
|
|
333
|
+
buttonActions: props.buttonActions,
|
|
334
|
+
builtPolyfillReq: props.builtPolyfillReq,
|
|
323
335
|
requestTraceId: props.requestTraceId,
|
|
324
336
|
dialogReq: props.dialogReq,
|
|
325
337
|
mode: props.mode,
|
|
@@ -361,7 +373,7 @@ export default {
|
|
|
361
373
|
provide('hireRelatMapRules', hireRelatMapRulesRef) // 组件对应的规则集合
|
|
362
374
|
|
|
363
375
|
provide('buttonActions', props.buttonActions)
|
|
364
|
-
provide('components',
|
|
376
|
+
provide('components', componentsRef)
|
|
365
377
|
provide('selects', toRef(props, 'selects'))
|
|
366
378
|
provide('_rootInstance', instance)
|
|
367
379
|
provide('rootValue', computed({
|
|
@@ -381,13 +393,27 @@ export default {
|
|
|
381
393
|
provide('_parentDynamicMapComp', props.parentDynamicMapComp)
|
|
382
394
|
provide('_selectionsObj', props.selectionsObj)
|
|
383
395
|
provide('_polyfillConfigs', props.polyfillConfigs)
|
|
384
|
-
|
|
396
|
+
const requestTraceIdRef = toRef(props, 'requestTraceId')
|
|
397
|
+
provide('requestTraceId', requestTraceIdRef) // 所有渲染器调用的接口,都需要加次参数(生哥提)
|
|
385
398
|
|
|
386
399
|
const rootForm = ref(null)
|
|
387
400
|
provide('rootForm', rootForm)
|
|
388
401
|
|
|
389
402
|
const validate = (cb) => {
|
|
390
|
-
|
|
403
|
+
if (OPEN_DATA_RULES) {
|
|
404
|
+
validateByData({
|
|
405
|
+
rootConfig: props.config,
|
|
406
|
+
rootValue: props.modelValue,
|
|
407
|
+
mode: props.mode,
|
|
408
|
+
lang: props.lang,
|
|
409
|
+
messageInstance: props.messageInstance,
|
|
410
|
+
formRef:rootForm,
|
|
411
|
+
cb,
|
|
412
|
+
dynamicMapComp,
|
|
413
|
+
})
|
|
414
|
+
} else {
|
|
415
|
+
toValidate(rootForm, cb, dynamicMapComp)
|
|
416
|
+
}
|
|
391
417
|
}
|
|
392
418
|
provide('_validate', validate)
|
|
393
419
|
expose({
|
package/src/resolver-web.vue
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import getNativeComps from './components/patchComponents-web'
|
|
3
|
-
import { ElMessage, ElMessageBox, formContextKey } from "element-plus"
|
|
3
|
+
import { ElMessage, ElMessageBox, formContextKey, useFormItem } from "element-plus"
|
|
4
4
|
import { loadingInstance } from './components/loading'
|
|
5
5
|
import { computed, provide, ref, useAttrs } from 'vue';
|
|
6
6
|
import Resolver from './resolver-common.vue'
|
|
@@ -48,6 +48,8 @@ const attrs = useAttrs()
|
|
|
48
48
|
const resolverRef = ref(null)
|
|
49
49
|
|
|
50
50
|
provide('_formContextKey', formContextKey)
|
|
51
|
+
provide('_useFormItem', useFormItem)
|
|
52
|
+
|
|
51
53
|
|
|
52
54
|
defineExpose({
|
|
53
55
|
dynamicMapComp: computed({
|
package/src/utils/common.js
CHANGED
|
@@ -637,6 +637,7 @@ export function assignmentPathVal(obj = {}, path, val, separator = '.') {
|
|
|
637
637
|
const currentIdx = parseInt(match[2])
|
|
638
638
|
if (!Number.isNaN(currentIdx)) {
|
|
639
639
|
!retObj[currentIdx] && (retObj[currentIdx] = {})
|
|
640
|
+
retObj = retObj[currentIdx]
|
|
640
641
|
}
|
|
641
642
|
}
|
|
642
643
|
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
export class LazyLoader {
|
|
2
|
+
el = null
|
|
3
|
+
io = null
|
|
4
|
+
isInit = false
|
|
5
|
+
options = {}
|
|
6
|
+
constructor(el, options) {
|
|
7
|
+
this.options = options
|
|
8
|
+
this.el = el
|
|
9
|
+
let { viewport, direction = 'vertical', threshold = '10px'} = this.options
|
|
10
|
+
let rootMargin
|
|
11
|
+
switch (direction) {
|
|
12
|
+
case 'vertical':
|
|
13
|
+
rootMargin = `${threshold} 0px`
|
|
14
|
+
break
|
|
15
|
+
case 'horizontal':
|
|
16
|
+
rootMargin = `0px ${threshold}`
|
|
17
|
+
break
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
// 观察视口与组件容器的交叉情况
|
|
22
|
+
this.io = new window.IntersectionObserver(this.intersectionHandler.bind(this), {
|
|
23
|
+
rootMargin,
|
|
24
|
+
root: viewport,
|
|
25
|
+
threshold: [0, Number.MIN_VALUE, 0.01]
|
|
26
|
+
});
|
|
27
|
+
this.io.observe(el);
|
|
28
|
+
} catch (e) {
|
|
29
|
+
this.toInit()
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
intersectionHandler (entries) {
|
|
33
|
+
if (
|
|
34
|
+
// 正在交叉
|
|
35
|
+
entries[0].isIntersecting ||
|
|
36
|
+
// 交叉率大于0
|
|
37
|
+
entries[0].intersectionRatio
|
|
38
|
+
) {
|
|
39
|
+
this.toInit()
|
|
40
|
+
this.io?.unobserve(this.el)
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
toInit () {
|
|
44
|
+
// 此时说明骨架组件即将被切换
|
|
45
|
+
this.options?.beforeInit?.()
|
|
46
|
+
|
|
47
|
+
// 此时可以准备加载懒加载组件的资源
|
|
48
|
+
this.options?.beginLoading?.()
|
|
49
|
+
|
|
50
|
+
// 由于函数会在主线程中执行,加载懒加载组件非常耗时,容易卡顿
|
|
51
|
+
// 所以在requestAnimationFrame回调中延后执行
|
|
52
|
+
this.requestAnimationFrame(() => {
|
|
53
|
+
this.isInit = true
|
|
54
|
+
this.options?.init?.()
|
|
55
|
+
})
|
|
56
|
+
}
|
|
57
|
+
requestAnimationFrame (callback) {
|
|
58
|
+
const { maxWaitingTime = 50 } = this.options
|
|
59
|
+
// 防止等待太久没有执行回调
|
|
60
|
+
// 设置最大等待时间
|
|
61
|
+
setTimeout(() => {
|
|
62
|
+
if (this.isInit) return
|
|
63
|
+
callback()
|
|
64
|
+
}, maxWaitingTime)
|
|
65
|
+
|
|
66
|
+
// 兼容不支持requestAnimationFrame 的浏览器
|
|
67
|
+
return (window.requestAnimationFrame || ((callback) => setTimeout(callback, 1000 / 60)))(callback)
|
|
68
|
+
}
|
|
69
|
+
}
|