vue-create-shadow-app
Version:
create vue app in shadowDom
92 lines (91 loc) • 3.01 kB
JavaScript
import { defineComponent, createApp, ref, getCurrentInstance, onMounted, h } from "vue";
import { isPlainObject, extend, hyphenate } from "@vue/shared";
function createShadowApp(rootComponent, rootProps, extraOptions) {
const Comp = defineComponent(rootComponent, extraOptions);
if (isPlainObject(Comp)) extend(Comp, extraOptions);
let shadowRoot = null;
let fakeCE = null;
const rawApp = createApp({
setup() {
const rootInstance = ref(null);
const instance = getCurrentInstance();
if (!instance) {
throw new Error("no instance");
}
fakeCE._instance = instance;
instance.ce = fakeCE;
instance.isCE = true;
const dispatch = (event, args) => {
fakeCE.dispatchEvent(
new CustomEvent(
event,
isPlainObject(args[0]) ? extend({ detail: args }, args[0]) : { detail: args }
)
);
};
instance.emit = (event, ...args) => {
dispatch(event, args);
if (hyphenate(event) !== event) {
dispatch(hyphenate(event), args);
}
};
onMounted(() => {
instance.exposed = {};
instance.exposeProxy = rootInstance.value;
});
return () => {
const vnode = h(rootComponent, { ...rootProps, ref: rootInstance });
vnode.ce = (instance2) => {
instance2.ce = instance2.root.ce;
};
return vnode;
};
}
});
const converted = Object.create(rawApp);
converted.mount = (rootContainer, isHydrate, isSVG) => {
const rootElm = typeof rootContainer === "string" ? document.querySelector(rootContainer) : rootContainer;
if (!rootElm) {
throw new Error(`dom ${rootContainer} is not found`);
}
fakeCE = rootElm;
fakeCE._nonce = extraOptions == null ? void 0 : extraOptions.nonce;
fakeCE._instance = null;
fakeCE._injectChildStyle = function(comp) {
this._applyStyles(comp.styles, comp);
};
fakeCE._removeChildStyle = () => {
};
fakeCE._styleChildren = /* @__PURE__ */ new WeakSet();
fakeCE._applyStyles = function(styles2, owner) {
if (!styles2) return;
if (owner) {
if (owner === rootComponent || this._styleChildren.has(owner)) {
return;
}
this._styleChildren.add(owner);
}
const nonce = this._nonce;
for (let i = styles2.length - 1; i >= 0; i--) {
const s = document.createElement("style");
if (nonce) s.setAttribute("nonce", nonce);
s.textContent = styles2[i];
this.shadowRoot.prepend(s);
}
};
shadowRoot = rootElm.attachShadow({ mode: "open" });
const { styles } = Comp;
fakeCE._applyStyles(styles);
const appRoot = document.createElement("div");
shadowRoot.appendChild(appRoot);
return rawApp.mount(appRoot, isHydrate, isSVG);
};
converted.use = (plugin, ...args) => {
rawApp.use(plugin, ...args);
return converted;
};
return converted;
}
export {
createShadowApp
};