前言
上文实现渲染器系统
在前面两章中我们实现了 响应式系统 和 渲染器系统 ,这章节我们来实现 createApp 函数,我们要实现的 createApp 函数是一个工厂函数,用于创建一个应用程序实例。它接受一个根组件作为参数,并返回一个对象,该对象具有一个 mount 方法。mount 方法接受一个选择器字符串作为参数,用于指定应用程序将要挂载到哪个 DOM 元素上。在 mount 方法内部,createApp 函数使用了一个 effect 函数来监听根组件的渲染函数。如果应用程序尚未挂载,则调用根组件的渲染函数并将其返回的虚拟 DOM 对象挂载到指定的 DOM 元素上。如果应用程序已经挂载,则调用根组件的渲染函数并使用 patch 函数将新的虚拟 DOM 对象与旧的虚拟 DOM 对象进行比较并更新 DOM 元素。
话不多说,让我们开始把!
实现 createApp 函数
createApp 函数的作用我们在前言中已经讲了,直接上代码:
function createApp(rootComponent) {
// 创建应用程序实例的工厂函数,接受一个根组件作为参数
return {
mount(selector) {
// 挂载方法,接受一个选择器字符串作为参数
const root = document.querySelector(selector); // 获取要挂载到的 DOM 元素
let isMounted = false; // 标记应用程序是否已经挂载
let oldVnode = null; // 旧的虚拟 DOM 对象
effect(() => {
// 使用 effect 函数监听根组件的渲染函数
if (!isMounted) {
// 如果应用程序尚未挂载
oldVnode = rootComponent.render(); // 调用根组件的渲染函数并将其返回的虚拟 DOM 对象赋值给 oldVnode
mount(oldVnode, root); // 将 oldVnode 挂载到指定的 DOM 元素上
isMounted = true; // 将 isMounted 标记为 true
} else {
// 如果应用程序已经挂载
const newVnode = rootComponent.render(); // 调用根组件的渲染函数并将其返回的虚拟 DOM 对象赋值给 newVnode
patch(oldVnode, newVnode); // 使用 patch 函数将新的虚拟 DOM 对象与旧的虚拟 DOM 对象进行比较并更新 DOM 元素
oldVnode = newVnode; // 将 newVnode 赋值给 oldVnode
}
});
},
};
}
每一行已经标上了注释,我也就不过多讲解。直接让我们来测试吧:
const App = {
data: reactive({
count: 0,
}),
render() {
return h(
"div",
{
style: {
width: "200px",
height: "200px",
backgroundColor: "red",
},
},
[
h("h2", null, this.data.count),
h(
"button",
{
onClick: () => {
this.data.count++;
},
},
"+1"
),
]
);
},
};
createApp(App).mount("#root");
效果:
总结
至此,我们要实现的 MiniVue 的功能都已经实现了,尽管我们所实现的功能和代码都很简单,但对于初学者来说也是了解vue3的一种算作“开胃小菜吧”,之后的文章我会带着大家一步一步实现vue3内部的API。让我们一起期待吧,共勉!