vue3 createApp vs vue2 new Vue

vue2 的创建 vue 入口一般都是 new Vue(),但是 vue3 改成了 createApp。原因主要是,在 vue2 中,所有的 vue 实例是共享一个 Vue 构造函数对象的(包括全局指令/全局组件等)即 vue 上下文,无法做到完全隔离。比如你当下有个需求是,用一个页面,两个 vue 实例,一个有公共组件,使用:

Vue.component("my-compoenent", {
render: Vue.h("h1", {}, "Hello my-compoenent"),
});

此时,另一个 vue 实例,不希望有这个公共组件,是做不到的,因为他们都是公用同一个 vue 上下文。

而 vue3 的 createApp 正式解决这一类问题,createApp 可以创建一个 vue 上下文,返回 app,即可实现这种功能。

vue3 的这个改变也正是满足了当下微前端的需求,比如同一个页面,有两个团队分别用两个 vue 上下文,不希望有交集。

实例-全局登录弹窗

流程:

  1. 创建 vue 实例
  2. 获取$el 挂载到 body
  3. 暴露出实例的摧毁方法,移除 DOM
import { createApp, h } from "vue";
import Login from "./login.vue";

function create(Component, props) {
const app = createApp({
// 提供一个 render 函数,该函数能够接收到一个 `createElement` 函数用来创建 VNode
render() {
// 创建并返回 VNode
return h(Component, props);
},
});

const vm = app.mount(document.createElement("div"));
document.body.appendChild(vm.$el);

const comp = app.component;
comp.remove = () => {
try {
// 移除 DOM
app.unmount();
document.body.removeChild(vm.$el);
} catch (error) {}
};
return comp;
}
let promise = null;

export const login = async function (options) {
let comp;
try {
// 防止多个请求报失效导致的多次登录弹窗
if (!promise)
promise = new Promise((resolve, reject) => {
comp = create(Login, { resolve, reject, ...options });
});
await promise;
} catch (error) {
return Promise.reject(error);
} finally {
promise = null;
comp.remove();
}
};