目录渲染器相关概念渲染器阶段分析mount挂载阶段patch阶段简单实现编译器相关概念总结渲染器 相关概念 渲染器是Vue框架性能的核心,vue3的渲染器不仅包含传统的Diff算法
渲染器是Vue框架性能的核心,vue3的渲染器不仅包含传统的Diff算法,还独创了快捷的路径更新方式,可以充分利用渲染器提供的信息,大大提升更新和渲染的性能;
h
函数返回的就是一个对象,其作用是让编写的虚拟DOM变得更加轻松,换句话说h
函数就是一个辅助创建虚拟DOM的工具函数而已;虚拟DOM
就是用来描述真实DOM的普通js对象
,渲染器会将该对象渲染成真实DOM元素,当然虚拟DOM也可以描述组件
信息,而组件又可以理解成为一组DOM元素的封装
渲染函数
:一个组件要渲染的内容是通过渲染函数来描述的,也就是Vue中的render函数
,Vue会根据组件的render函数
的返回值拿到虚拟DOM
,然后将组件的内容渲染
出来;subTree
,最后再递归调用渲染器将subTree渲染
出来即可组件可以通过函数
或JS对象
来实现
// MyComponent 是一个对象
const MyComponent = {
render() {
return {
tag: "div",
props: {
onClick: () => alert("hello"),
},
children: "click me",
};
},
};
function mountComponent(vnode, container) {
// 调用组件函数,获取组件要渲染的内容(虚拟 DOM)
const subtree = vnode.tag();
// 递归地调用 renderer 渲染 subtree
renderer(subtree, container);
}
// MyComponent 是一个函数
function renderer(vnode, container) {
if (typeof vnode.tag === "string") {
// 说明 vnode 描述的是标签元素
// mountElement内部实现与下文的「实现renderer渲染器逻辑一致」
mountElement(vnode, container);
} else if (typeof vnode.tag === "function") {
// 说明 vnode 描述的是组件
mountComponent(vnode, container);
}
}
function mountComponent(vnode, container) {
// 调用组件函数,获取组件要渲染的内容(虚拟 DOM)
const subtree = vnode.tag();
// 递归地调用 renderer 渲染 subtree
renderer(subtree, container);
}
render与renderer
渲染器
,其作用是将虚拟DOM渲染为特定平台上的真实DOM,如在浏览器平台上,渲染器会将虚拟DOM渲染为真实DOM渲染
,是执行的动作渲染
,还可以用来执行其他操作,如激活已有DOM
、SSR
等;是更宽泛的概念,renderer包含render;创建节点
功能外,还需要实现精确的定点更新
对应变化的虚拟DOM到界面上,其内部原理简单,归根结底就是通过熟悉的DOM操作api
来完成渲染工作实现renderer渲染器
function renderer(vnode, container) {
// 使用 vnode.tag 作为标签名称创建对应的 DOM 元素
const el = document.createElement(vnode.tag);
// 遍历 vnode.props,将属性、事件添加到 DOM 元素
for (const key in vnode.props) {
if (/^on/.test(key)) {
// 如果 key 以 on 开头,说明它是事件
el.addEventListener(
key.substr(2).toLowerCase(), // 事件名称 onClick ---> click
vnode.props[key] // 事件处理函数
);
}
}
// 处理 children
if (typeof vnode.children === "string") {
// 如果 children 是字符串,说明它是元素的文本子节点
el.appendChild(document.createTextNode(vnode.children));
} else if (Array.isArray(vnode.children)) {
// 递归地调用 renderer 函数渲染子节点,使用当前元素 el 作为挂载点
vnode.children.forEach((child) => renderer(child, el));
}
// 将元素添加到挂载点下
container.appendChild(el);
}
具体代码实现逻辑
角色解析
具体作用
Vue3特殊内置组件解析
<template>
// Portal 把里面的内容挂载到 #app
<Portal target="#app">
<div class="overlay"></div>
</Portal>
</template>
mount就是将VNode挂载到真实DOM上
patch就是使用新的VNode和旧的VNode进行对比,用最少的资源实现DOM更新,也叫「打补丁」
渲染器接受两个参数,要被渲染的VNode和挂载点(承载内容的container)
function createRenderer() {
function render(vnode, container) {
if (vnode) {
// 存在旧节点 需要进行patch补丁更新
patch(container._vnode, vnode, container);
} else {
if (container._vnode) {
// 旧 vnode 存在,且新 vnode 不存在,此时渲染的是上一步中的节点值,说明是卸载(unmount)操作
container.innerhtml = "";
}
}
// 把 vnode 存储到 container._vnode 下,即后续渲染中的旧 vnode
container._vnode = vnode;
}
return {
render,
};
}
编译器在模板编译时可以识别哪些是静态属性,哪些是动态属性,从而在编译生成代码时可以将这些信息附加到编译后代码中,这样可以避免渲染器花费力气去寻找变更点
编译器和渲染器一样,不同之处在于编译器是将模板编译成渲染函数,而模板就是一个普通的字符串,编译器会分析该字符串并生成一个功能与之相同的渲染函数;
模板在Vue中体现在.vue
文件中的<template>
标签的内容,本身.vue
文件就是一个组件,编译器会将模板内容编译成渲染函数并添加到<script>
标签的组件对象上;
<template>
<div @click="login">
登录
</div>
</template>
<script>
export default {
data() {
},
methods: {
login: () => { }
}
}
</script>
//编译后
export default {
data() {},
methods: {
login: () => { }
},
render() {
return h('div', { onClick: login }, '登录')
}
}
通过将渲染器和编译器相配合,从而达到进一步提升性能的目的
组件的实现需要依赖于渲染器,模板的编译需要依赖于编译器,而且编译后的代码是根据渲染器和虚拟DOM的设计决定的,因此Vue中各个模块之间是相互关联、相互制约的;
模板工作原理:无论是模板还是直接手写渲染函数,对于一个组件来说,其渲染内容最终都是通过渲染函数产生的,然后渲染器再将渲染函数返回 的虚拟DOM渲染为真实DOM
以上就是Vue3渲染器与编译器深入浅析的详细内容,更多关于Vue3渲染器编译器的资料请关注编程网其它相关文章!
--结束END--
本文标题: Vue3渲染器与编译器深入浅析
本文链接: https://www.lsjlt.com/news/193877.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
下载Word文档到电脑,方便收藏和打印~
2024-01-12
2023-05-20
2023-05-20
2023-05-20
2023-05-20
2023-05-20
2023-05-20
2023-05-20
2023-05-20
2023-05-20
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0