前言
vue底层的三大核心系统包括了编译时,运行时,响应式系统,因为编译器的实现是比较复杂的,所以我们直接从运行时开始
主要实现
-
h()
实现读取vnode
-
mount()
实现处理vnode,将其挂载到指定节点
-
patch()
目录结构
- mini-vue
src
render.js
- index.html
复制代码
page
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>mini-vue</title>
</head>
<body>
<div id="app"></div>
<script src="./lib/render.js"></script>
<script>
// 1.runtime运行时节点配置vnode
const vnode = h("div", { class: "page-container" }, [
h("div", { class: "page-title-view" }, [
h("h1", { class: "title" }, "页面标题"),
]),
]);
// 2.将vnode挂在到指定节点上
mount(vnode, document.querySelector("#app"));
</script>
</body>
</html>
复制代码
render
/**
* 渲染器
* @param {string} tag
* @param {object} props
* @param {any} children
* @returns
*/
function h(tag, props, children) {
return {
tag,
props,
children,
};
}
/**
* 挂载器
* @param function vnode
* @param string node
*/
function mount(vnode, container) {
// 1.创建真实的节点,并在vnode上保留el
const el = (vnode.el = document.createElement(vnode.tag));
// 2.处理props
if (vnode.props) {
for (const key in vnode.props) {
const attr = vnode.props[key];
// 考虑到边界问题,判断传入的属性是普通属性还是点击事件
if (key.startsWith("on")) {
el.addEventLicener(key.slice(2).toLowerCase(), attr);
} else {
el.setAttribute(key, attr);
}
}
}
// 3.处理children
if (typeof vnode.children === "string") {
el.textContent = vnode.children;
} else {
vnode.children.forEach((item) => {
mount(item, el);
});
}
// 4.将el挂在到container上
container.appendChild(el);
}
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END