const App = {
render(context) {
return h("div", { id: "123", style: "color:red" }, [
h("p", null, String(context.state.value)),
h("div", { style: "color:blue" }, String(context.state.value * 2)),
]);
},
setup() {
const state = reactive({
value: 10,
});
window.state = state; //为了好改值
return { state };
},
};
createApp(App).mount(document.getElementById("app"));
实现h函数,该函数为返回vdom
//retrun vdom
function h(tag, props, children) {
return {
tag,
props,
children,
};
}
实现createApp函数,该函数返回mount方法
function createApp(rootComponent) {
return {
mount(rootContainer) {
const context = rootComponent.setup();
effectWatch(() => {
rootContainer.innerHTML = "";
const subTree = rootComponent.render(context);
mountElement(subTree, rootContainer);
});
},
};
}
实现mountElement函数,把虚拟dom转为真实dom,这里简单实现一下,直接挂载,不考虑vdom diff
//vdom => dom
function mountElement(vnode, rootContainer) {
const { tag, props, children } = vnode;
//tag
const el = document.createElement(tag);
//props
if (props) {
for (const key in props) {
const val = props[key];
el.setAttribute(key, val);
}
}
//chidren
//数组or字符串
if (typeof children === "string") {
const textNode = document.createTextNode(children);
el.append(textNode);
} else if (Array.isArray(children)) {
children.forEach((child) => {
mountElement(child, el);
});
}
rootContainer.append(el);
}
参考:
https://dafunk.gitee.io/views/vue/mini-vue-reactive.html https://github.com/mewcoder/codebase/tree/main/mini-vue3 https://github.com/ReySun/vue3-deep-dive-width-evan-you