-
type
参数描述了 HTML 元素的类型,例如h1
,div
等等… -
props
参数的工作方式与 React/Vue 中的 props 完全相同——它允许我们将数据(属性)传递给元素 -
children
当前元素内其他子节点。
让我们看看它是如何使用的。
const view = () =>
h('div', {}, [
h('h1', {}, ['Hello']),
h('p', {}, ['from virtual DOM!']),
h('p', {}, ['from virtual DOM!']),
h('p', {}, ['from virtual DOM!']),
h('p', {}, ['from virtual DOM!']),
]);
我们创建了一个div
元素,里面有h1
和p
元素。这些元素中的每一个都有一个文本节点作为其子节点。
现在是时候将这个虚拟树转换为实际的 DOM。
render
方法
让我们实现一个render
功能。
const render = (root, view) => {
const rendered = view();
diff(root, null, rendered);
};
const diff = (root, oldNode, newNode, index) => {
// 判断节点是否变化,有变化则更新
};
render(app, view);
渲染函数首先调用view函数,然后运行 diff 函数,该函数接受一个根元素(来自真实 DOM)、旧的虚拟节点(因为我们第一次渲染它是null
)和新的虚拟节点 。
diff
方法
基本上,该diff
函数只会将 oldNode 与 newNode 进行比较,看看它是否需要更新root
.
现在让我们看看如何实现 diff 函数。
const diff = (root, oldNode, newNode, index) => {
// 判断节点是否变化,有变化则更新
if (!oldNode) {
root.appendChild(createElement(newNode));
}
};
如果没有oldNode
,我们需要创建这个元素并将其插入 DOM。首先,我们使用该函数创建一个元素createElement
,然后我们在第二个实现该函数,然后我们appendChild
在一个真实的 DOM 元素上使用该方法,将该节点附加为其子节点。
让我们实现createElement
功能。
const createElement = (node) => {
if (typeof node === 'string') {
return document.createTextNode(node);
}
const el = document.createElement(node.type);
node.children.map(createElement).forEach(el.appendChild.bind(el));
return el;
};
如果一个节点是一个文本节点(例如“Hello”),我们只需使用document.createTextNode
函数渲染它。
如果不是,我们创建给定类型的元素,document.createElement
然后循环遍历它的每个子元素,createElement
递归调用函数。这样我们就创建了整个树并返回它。
让我们看看到目前为止我们编写的完整代码:
const app = document.querySelector('#app');
const h = (type, props = {}, children = []) => ({
type,
props,
children,
});
const view = () =>
h("div", {}, [
h("h1", {}, ["Hello"]),
h("p", {}, ["from virtual DOM!"]),
h("p", {}, ["from virtual DOM!"]),
h("p", {}, ["from virtual DOM!"]),
h("p", {}, ["from virtual DOM!"]),
]);
const render = (root, view) => {
const rendered = view();
diff(root, null, rendered);
};
const diff = (root, oldNode, newNode, index) => {
// 判断节点是否变化,有变化则更新
if (!oldNode) {
root.appendChild(createElement(newNode));
}
};
const createElement = (node) => {
if (typeof node === 'string') {
return document.createTextNode(node);
}
const el = document.createElement(node.type);
node.children.map(createElement).forEach(el.appendChild.bind(el));
##### 框架相关
原生JS虽能实现绝大部分功能,但要么就是过于繁琐,要么就是存在缺陷,故绝大多数开发者都会首选框架开发方案。现阶段较热门是React、Vue两大框架,两者工作原理上存在共通点,也存在一些不同点,对于校招来说,不需要两个框架都学得特别熟,一般面试官会针对你简历中写的框架进行提问。
在框架方面,**生命周期、钩子函数、虚拟DOM这些基本知识是必须要掌握的**,在学习的过程可以结合框架的官方文档
**Vue框架**
>**知识要点:**
>**1. vue-cli工程**
>**2. vue核心知识点**
>**3. vue-router**
>**4. vuex**
>**5. http请求**
>**6. UI样式**
>**7. 常用功能**
>**8. MVVM设计模式**
![](https://img-blog.csdnimg.cn/img_convert/9fcd79fec5cb04f5569049d8dc54fc24.webp?x-oss-process=image/format,png)
**React框架**
>**知识要点:**
>**1. 基本知识**
>**2. React 组件**
>**3. React Redux**
>**4. React 路由**
![](https://img-blog.csdnimg.cn/img_convert/b89759c33b9e0856d7c66ab0f1b5ee7c.webp?x-oss-process=image/format,png)
ue核心知识点**
>**3. vue-router**
>**4. vuex**
>**5. http请求**
>**6. UI样式**
>**7. 常用功能**
>**8. MVVM设计模式**
[外链图片转存中...(img-h366VflJ-1718099990756)]
**React框架**
>**知识要点:**
>**1. 基本知识**
>**2. React 组件**
>**3. React Redux**
>**4. React 路由**
[外链图片转存中...(img-zUYlyb8Z-1718099990757)]