初识渲染器
// JS对象描述UI
const title = {
// 标签名称
tag: "h1",
// 标签属性
props: {
onclick: handler,
},
// 子节点
children: [{ tag: "span" }],
} // 对应的vue模版
`<h1 onclick="handler"><span></span></h1>`;
// import { h } from "vue";
// export default {
// render(h) {
// return h("h1", {
// onclick: handler,
// }); // 虚拟dom
// },
// };
// 虚拟DOM就是用js对象来描述真实的DOM结构
const vnode = {
// 标签名称
tag: "div",
// 标签属性
props: {
onclick: () => alert("hello world"),
},
// 子节点
children: "click",
};
// 渲染器 把虚拟DOM转换成真实DOM
//普通元素
function mountElement(vnode, container) {
const el = document.createElement(vnode.tag);
for (const key in vnode.props) {
if (/^on/.test(key)) {
// 如果on开头的属性,则说明是事件
el.addEventListener(key.slice(2).toLowerCase(), vnode.props[key]);
}
}
if (typeof vnode.children === "string") {
el.appendChild(document.createTextNode(vnode.children));
} else if (Array.isArray(vnode.children)) {
// 递归调用renderer函数渲染子节点,使用当前元素el作为挂载点
vnode.children.forEach((child) => {
renderer(child, el);
});
// 将元素添加到挂载点
container.appendChild(el);
}
}
// mountElement(vnode, document.body);
// 组件函数形式
const MyComponent = function () {
return {
// 标签名称
tag: "div",
// 标签属性
props: {
onclick: () => alert("hello world"),
},
// 子节点
children: "click me",
};
};
// 组件对象形式
const MyComponent2 = {
render() {
return {
// 标签名称
tag: "div",
// 标签属性
props: {
onclick: () => alert("hello world"),
},
// 子节点
children: "click me",
};
},
};
const vComNode = {
tag:MyComponent,
tag2:MyComponent2,
}
//组件function形式渲染
function mountComponent(vnode, container) {
// 调用组件函数,获取组件要渲染的内容(虚拟DOM)
const subtree = vnode.tag();
// 递归调用renderer函数渲染子组件subtree
renderer(subtree, container);
}
// 组件对象 形式
function mountComponent(vnode, container) {
// 调用组件函数,获取组件要渲染的内容(虚拟DOM)
const subtree = vnode.tag.render();
// 递归调用renderer函数渲染子组件subtree
renderer(subtree, container);
}
function renderer(vnode, container) {
if (typeof vnode.tag==='string') {
mountElement(vnode, container);
} else if (typeof vnode.tag === "function") {
mountComponent(vnode, container);
}else if (typeof vnode.tag === "object") {
mountComponent2(vnode, container);
}
}
Last updated