/
dynamic.js
88 lines (77 loc) 路 2.22 KB
/
dynamic.js
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
import React, { Component } from 'react';
const cached = {};
function registerModel(app, model) {
model = model.default || model;
if (!cached[model.namespace]) {
app.model(model);
cached[model.namespace] = 1;
}
}
let defaultLoadingComponent = () => null;
function asyncComponent(config) {
const { resolve } = config;
return class DynamicComponent extends Component {
constructor(...args) {
super(...args);
this.LoadingComponent = config.LoadingComponent || defaultLoadingComponent;
this.state = {
AsyncComponent: null,
};
this.load();
}
componentDidMount() {
this.mounted = true;
}
componentWillUnmount() {
this.mounted = false;
}
load() {
resolve().then(m => {
const AsyncComponent = m.default || m;
if (this.mounted) {
this.setState({ AsyncComponent });
} else {
this.state.AsyncComponent = AsyncComponent; // eslint-disable-line
}
});
}
render() {
const { AsyncComponent } = this.state;
const { LoadingComponent } = this;
if (AsyncComponent) return <AsyncComponent {...this.props} />;
return <LoadingComponent {...this.props} />;
}
};
}
export default function dynamic(config) {
const { app, models: resolveModels, component: resolveComponent } = config;
return asyncComponent({
resolve:
config.resolve ||
function() {
const models = typeof resolveModels === 'function' ? resolveModels() : [];
const component = resolveComponent();
return new Promise(resolve => {
Promise.all([...models, component]).then(ret => {
if (!models || !models.length) {
return resolve(ret[0]);
} else {
const len = models.length;
ret.slice(0, len).forEach(m => {
m = m.default || m;
if (!Array.isArray(m)) {
m = [m];
}
m.map(_ => registerModel(app, _));
});
resolve(ret[len]);
}
});
});
},
...config,
});
}
dynamic.setDefaultLoadingComponent = LoadingComponent => {
defaultLoadingComponent = LoadingComponent;
};