@muban/muban
Version:
Writing components for server-rendered HTML
102 lines (101 loc) • 3.86 kB
JavaScript
import { devtoolsInitApp, devtoolsUnmountApp } from '../utils/devtools';
import { registerGlobalComponent } from '../utils/global';
import { mount } from '../utils/mount';
const version = '10';
export function createAppContext() {
return {
app: null,
config: {
// isNativeTag: NO,
// performance: false,
// globalProperties: {},
// optionMergeStrategies: {},
// isCustomElement: NO,
// errorHandler: undefined,
// warnHandler: undefined,
},
components: {},
provides: Object.create(null),
};
}
let uid = 0;
export function createApp(rootComponent) {
// if (rootProps != null && !isObject(rootProps)) {
// console.warn(`root props passed to app.mount() must be an object.`);
// rootProps = null;
// }
const context = createAppContext();
let isMounted = false;
// eslint-disable-next-line no-multi-assign
const app = (context.app = {
_uid: uid++,
_component: rootComponent,
_instance: null,
_props: null,
_container: null,
_context: context,
version,
get config() {
return context.config;
},
set config(v) {
// eslint-disable-next-line no-console
console.warn(`app.config cannot be replaced. Modify individual options instead.`);
},
component(...components) {
registerGlobalComponent(...components);
return app;
},
mount(rootContainer, template, data) {
var _a, _b;
if (!isMounted) {
const component = mount(app, rootComponent, rootContainer, template, data);
app._instance = component === null || component === void 0 ? void 0 : component.__instance;
if (app._instance) {
app._instance.appContext = context;
}
isMounted = true;
app._container = (_b = (_a = app._instance) === null || _a === void 0 ? void 0 : _a.element) !== null && _b !== void 0 ? _b : null;
// for devtools and telemetry
// (rootContainer as any).__vue_app__ = app;
// TODO: devtools
// if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {
devtoolsInitApp(app, version);
// }
return component;
}
// eslint-disable-next-line no-console
console.warn(`App has already been mounted.\n` +
`If you want to remount the same app, move your app creation logic ` +
`into a factory function and create fresh app instances for each ` +
`mount - e.g. \`const createMyApp = () => createApp(App)\``);
},
unmount() {
if (isMounted) {
// TODO unmount original container
// render(null, app._container);
// TODO: devtools
// if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {
devtoolsUnmountApp(app);
// }
}
else {
// eslint-disable-next-line no-console
console.warn(`Cannot unmount an app that is not mounted.`);
}
},
provide(key, value) {
if (key in context.provides) {
// eslint-disable-next-line no-console
console.warn(`App already provides property with key "${String(key)}". ` +
`It will be overwritten with the new value.`);
}
// TypeScript doesn't allow symbols as index type
// https://github.com/Microsoft/TypeScript/issues/24587
context.provides[key] = value;
return app;
},
});
context.app = app;
return app;
}