# Vue运行机制 >面试题:介绍一下 Vue3 内部的运行机制是怎样的? Vue3 整体可以分为几大核心模块: - 响应式系统 - 编译器 - 渲染器 **如何描述UI** 思考🤔:UI涉及到的信息有哪些? 1. DOM元素 2. 属性 3. 事件 4. 元素的层次结构 思考🤔:如何在 JS 中描述这些信息? 考虑使用对象来描述上面的信息 ```html
一个简易版渲染器的实现思路:
1. 创建元素
2. 为元素添加属性和事件
3. 处理children
```js
function renderer(vnode, container){
// 1. 创建元素
const el = document.createElement(vnode.tag);
// 2. 遍历 props,为元素添加属性
for (const key in vnode.props) {
if (/^on/.test(key)) {
// 如果 key 以 on 开头,说明它是事件
el.addEventListener(
key.substr(2).toLowerCase(), // 事件名称 onClick --->click
vnode.props[key] // 事件处理函数
);
}
}
// 3. 处理children
if(typeof vnode.children === 'string'){
el.appendChild(document.createTextNode(vnode.children))
} else if(Array.isArray(vnode.children)) {
// 递归的调用 renderer
vnode.children.forEach(child => renderer(child, el))
}
container.appendChild(el)
}
```
**组件的本质**
组件本质就是**一组 DOM 元素**的封装。
假设函数代表一个组件:
```js
// 这个函数就可以当作是一个组件
const MyComponent = function () {
return {
tag: "div",
props: {
onClick: () => alert("hello"),
},
children: "click me",
};
};
```
vnode 的 tag 就不再局限于 html 元素,而是可以写作这个函数名:
```js
const vnode = {
tag: MyComponent
}
```
渲染器需要新增针对这种 tag 类型的处理:
```js
function renderer(vnode, container) {
if (typeof vnode.tag === "string") {
// 说明 vnode 描述的是标签元素
mountElement(vnode, container);
} else if (typeof vnode.tag === "function") {
// 说明 vnode 描述的是组件
mountComponent(vnode, container);
}
}
```
组件也可以使用对象的形式:
```js
const MyComponent = {
render(){
return {
tag: "div",
props: {
onClick: () => alert("hello"),
},
children: "click me",
};
}
}
```
```js
function renderer(vnode, container) {
if (typeof vnode.tag === "string") {
// 说明 vnode 描述的是标签元素
mountElement(vnode, container);
} else if (typeof vnode.tag === "object") {
// 说明 vnode 描述的是组件
mountComponent(vnode, container);
}
}
```
**响应式系统**
总结:当模板编译成的渲染函数执行时,渲染函数内部用到的响应式数据会和渲染函数本身构成依赖关系,之后只要响应式数据发生变化,渲染函数就会重新执行。
> 面试题:介绍一下 Vue3 内部的运行机制是怎样的?
>
> 参考答案:
>
> Vue3 是一个声明式的框架。声明式的好处在于,它直接描述结果,用户不需要关注过程。Vue.js 采用模板的方式来描述 UI,但它同样支持使用虚拟 DOM 来描述 UI。**虚拟 DOM 要比模板更加灵活,但模板要比虚拟 DOM 更加直观**。
>
> 当用户使用模板来描述 UI 的时候,内部的 **编译器** 会将其编译为渲染函数,渲染函数执行后能够确定响应式数据和渲染函数之间的依赖关系,之后响应式数据一变化,渲染函数就会重新执行。
>
> 渲染函数执行的结果是得到虚拟 DOM,之后就需要 **渲染器** 来将虚拟 DOM 对象渲染为真实 DOM 元素。它的工作原理是,递归地遍历虚拟 DOM 对象,并调用原生 DOM API 来完成真实 DOM 的创建。渲染器的精髓在于后续的更新,它会通过 Diff 算法找出变更点,并且只会更新需要更新的内容。
>
> 编译器、渲染器、响应式系统都是 Vue 内部的核心模块,它们共同构成一个有机的整体,不同模块之间互相配合,进一步提升框架性能。
---
-EOF-