feat: 🎸 添加 didMount 和 willUnmount 两个基本的生命周期

This commit is contained in:
牧毅 2020-08-13 21:04:21 +08:00
parent 779ea7c718
commit e33a95e479
7 changed files with 153 additions and 47 deletions

View File

@ -2,6 +2,9 @@ export const RAX_CHUNK_NAME = {
ClassDidMountBegin: 'RaxComponentClassDidMountBegin',
ClassDidMountContent: 'RaxComponentClassDidMountContent',
ClassDidMountEnd: 'RaxComponentClassDidMountEnd',
ClassWillUnmountBegin: 'RaxComponentClassWillUnmountBegin',
ClassWillUnmountContent: 'RaxComponentClassWillUnmountContent',
ClassWillUnmountEnd: 'RaxComponentClassWillUnmountEnd',
ClassRenderBegin: 'RaxComponentClassRenderBegin',
ClassRenderPre: 'RaxComponentClassRenderPre',
ClassRenderJSX: 'RaxComponentClassRenderJSX',
@ -9,4 +12,7 @@ export const RAX_CHUNK_NAME = {
MethodsBegin: 'RaxComponentMethodsBegin',
MethodsContent: 'RaxComponentMethodsContent',
MethodsEnd: 'RaxComponentMethodsEnd',
LifeCyclesBegin: 'RaxComponentLifeCyclesBegin',
LifeCyclesContent: 'RaxComponentLifeCyclesContent',
LifeCyclesEnd: 'RaxComponentLifeCyclesEnd',
};

View File

@ -84,12 +84,33 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
linkAfter: [RAX_CHUNK_NAME.ClassDidMountBegin, RAX_CHUNK_NAME.ClassDidMountContent],
});
next.chunks.push({
type: ChunkType.STRING,
fileType: FileType.JSX,
name: RAX_CHUNK_NAME.ClassWillUnmountBegin,
content: `componentWillUnmount() {`,
linkAfter: [
CLASS_DEFINE_CHUNK_NAME.Start,
CLASS_DEFINE_CHUNK_NAME.InsVar,
CLASS_DEFINE_CHUNK_NAME.InsMethod,
RAX_CHUNK_NAME.ClassDidMountEnd,
],
});
next.chunks.push({
type: ChunkType.STRING,
fileType: FileType.JSX,
name: RAX_CHUNK_NAME.ClassWillUnmountEnd,
content: `}`,
linkAfter: [RAX_CHUNK_NAME.ClassWillUnmountBegin, RAX_CHUNK_NAME.ClassWillUnmountContent],
});
next.chunks.push({
type: ChunkType.STRING,
fileType: FileType.JSX,
name: RAX_CHUNK_NAME.ClassRenderBegin,
content: 'render() {',
linkAfter: [RAX_CHUNK_NAME.ClassDidMountEnd],
linkAfter: [RAX_CHUNK_NAME.ClassDidMountEnd, RAX_CHUNK_NAME.ClassWillUnmountEnd],
});
next.chunks.push({

View File

@ -1,3 +1,4 @@
import _ from 'lodash';
import { CLASS_DEFINE_CHUNK_NAME, DEFAULT_LINK_AFTER } from '../../../const/generator';
import { RAX_CHUNK_NAME } from './const';
@ -7,7 +8,6 @@ import {
BuilderComponentPlugin,
BuilderComponentPluginFactory,
ChunkType,
CodeGeneratorError,
FileType,
ICodeChunk,
ICodeStruct,
@ -34,53 +34,86 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
...pre,
};
// TODO: Rax 程序的生命周期暂未明确,此处先屏蔽
// @see https://yuque.antfin-inc.com/mo/spec/spec-low-code-building-schema#XMeF5
// Rax 先只支持 didMount 和 willUnmount 吧
// const ir = next.ir as IContainerInfo;
const ir = next.ir as IContainerInfo;
const lifeCycles = ir.lifeCycles;
// if (ir.lifeCycles) {
// const lifeCycles = ir.lifeCycles;
// const chunks = Object.keys(lifeCycles).map<ICodeChunk>(lifeCycleName => {
// const normalizeName = cfg.normalizeNameMapping[lifeCycleName] || lifeCycleName;
// const exportName = cfg.exportNameMapping[lifeCycleName] || lifeCycleName;
// if (normalizeName === 'constructor') {
// return {
// type: ChunkType.STRING,
// fileType: cfg.fileType,
// name: CLASS_DEFINE_CHUNK_NAME.ConstructorContent,
// content: getFuncExprBody(
// (lifeCycles[lifeCycleName] as JSExpression).value,
// ),
// linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.ConstructorStart]],
// };
// }
// if (normalizeName === 'render') {
// return {
// type: ChunkType.STRING,
// fileType: cfg.fileType,
// name: RAX_CHUNK_NAME.ClassRenderPre,
// content: getFuncExprBody(
// (lifeCycles[lifeCycleName] as JSExpression).value,
// ),
// linkAfter: [RAX_CHUNK_NAME.ClassRenderStart],
// };
// }
if (lifeCycles && !_.isEmpty(lifeCycles)) {
Object.entries(lifeCycles).forEach(([lifeCycleName, lifeCycleMethodExpr]) => {
const normalizeName = cfg.normalizeNameMapping[lifeCycleName] || lifeCycleName;
const exportName = cfg.exportNameMapping[lifeCycleName] || lifeCycleName;
// return {
// type: ChunkType.STRING,
// fileType: cfg.fileType,
// name: CLASS_DEFINE_CHUNK_NAME.InsMethod,
// content: transformFuncExpr2MethodMember(
// exportName,
// (lifeCycles[lifeCycleName] as JSExpression).value,
// ),
// linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.InsMethod]],
// };
// });
next.chunks.push({
type: ChunkType.STRING,
fileType: cfg.fileType,
name: RAX_CHUNK_NAME.LifeCyclesContent,
content: `${exportName}: (${lifeCycleMethodExpr.value}),`,
linkAfter: [RAX_CHUNK_NAME.LifeCyclesBegin],
});
// next.chunks.push.apply(next.chunks, chunks);
// }
if (normalizeName === 'didMount') {
next.chunks.push({
type: ChunkType.STRING,
fileType: cfg.fileType,
name: RAX_CHUNK_NAME.ClassDidMountContent,
content: `this._lifeCycles.${exportName}();`,
linkAfter: [RAX_CHUNK_NAME.ClassDidMountBegin],
});
} else if (normalizeName === 'willUnmount') {
next.chunks.push({
type: ChunkType.STRING,
fileType: cfg.fileType,
name: RAX_CHUNK_NAME.ClassWillUnmountContent,
content: `this._lifeCycles.${exportName}();`,
linkAfter: [RAX_CHUNK_NAME.ClassWillUnmountBegin],
});
} else {
// TODO: print warnings? Unknown life cycle
}
});
next.chunks.push({
type: ChunkType.STRING,
fileType: cfg.fileType,
name: CLASS_DEFINE_CHUNK_NAME.InsVar,
content: `_lifeCycles = this._defineLifeCycles();`,
linkAfter: [CLASS_DEFINE_CHUNK_NAME.Start],
});
next.chunks.push({
type: ChunkType.STRING,
fileType: cfg.fileType,
name: RAX_CHUNK_NAME.LifeCyclesBegin,
content: `
_defineLifeCycles() {
const __$$lifeCycles = ({
`,
linkAfter: [RAX_CHUNK_NAME.ClassRenderEnd, CLASS_DEFINE_CHUNK_NAME.InsPrivateMethod],
});
next.chunks.push({
type: ChunkType.STRING,
fileType: cfg.fileType,
name: RAX_CHUNK_NAME.LifeCyclesEnd,
content: `
});
// 为所有的方法绑定上下文
Object.entries(__$$lifeCycles).forEach(([lifeCycleName, lifeCycleMethod]) => {
if (typeof lifeCycleMethod === 'function') {
__$$lifeCycles[lifeCycleName] = (...args) => {
return lifeCycleMethod.apply(this._context, args);
}
}
});
return __$$lifeCycles;
}
`,
linkAfter: [RAX_CHUNK_NAME.LifeCyclesBegin, RAX_CHUNK_NAME.LifeCyclesContent],
});
}
return next;
};

View File

@ -46,7 +46,11 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
_defineMethods() {
const __$$methods = ({
`,
linkAfter: [RAX_CHUNK_NAME.ClassRenderEnd, CLASS_DEFINE_CHUNK_NAME.InsPrivateMethod],
linkAfter: [
RAX_CHUNK_NAME.ClassRenderEnd,
CLASS_DEFINE_CHUNK_NAME.InsPrivateMethod,
RAX_CHUNK_NAME.LifeCyclesEnd,
],
});
next.chunks.push({

View File

@ -28,6 +28,8 @@ class Home$$Page extends Component {
this._dataSourceEngine.reloadDataSource();
}
componentWillUnmount() {}
render() {
const __$$context = this._context;

View File

@ -43,8 +43,16 @@ class Home$$Page extends Component {
_utils = this._defineUtils();
_lifeCycles = this._defineLifeCycles();
componentDidMount() {
this._dataSourceEngine.reloadDataSource();
this._lifeCycles.didMount();
}
componentWillUnmount() {
this._lifeCycles.willUnmount();
}
render() {
@ -179,6 +187,29 @@ class Home$$Page extends Component {
return utils;
}
_defineLifeCycles() {
const __$$lifeCycles = {
didMount: function didMount() {
this.utils.Toast.show(`Hello ${this.state.user.name}!`);
},
willUnmount: function didMount() {
this.utils.Toast.show(`Bye, ${this.state.user.name}!`);
},
};
//
Object.entries(__$$lifeCycles).forEach(([lifeCycleName, lifeCycleMethod]) => {
if (typeof lifeCycleMethod === 'function') {
__$$lifeCycles[lifeCycleName] = (...args) => {
return lifeCycleMethod.apply(this._context, args);
};
}
});
return __$$lifeCycles;
}
_defineMethods() {
const __$$methods = {
hello: function hello() {

View File

@ -52,7 +52,16 @@
],
},
props: {},
lifeCycles: {},
lifeCycles: {
didMount: {
type: 'JSExpression',
value: 'function didMount(){\n this.utils.Toast.show(`Hello ${this.state.user.name}!`);\n}',
},
willUnmount: {
type: 'JSExpression',
value: 'function didMount(){\n this.utils.Toast.show(`Bye, ${this.state.user.name}!`);\n}',
},
},
methods: {
hello: {
type: 'JSExpression',