文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Vue.js设计与实现之十一-渲染器的设计

2024-12-02 03:38

关注

1、写在前面

在Vue.js框架很多功能依赖渲染器实现,也是框架性能的核心,能够直接影响框架性能。对此,Vue.js3的渲染器通过快捷路径更新的方式,利用编译器提供的信息提升性能。

2、渲染器和响应系统的结合

渲染器是用来执行渲染任务的,可以在浏览器平台来渲染真实DOM元素,它还能实现框架跨平台能力。

前面已经实现了reactivity的源码,为了后续方便讲解后续的操作,对此可以直接使用vue.js3的源码导入使用。

<script src="https://unpkg.com/@vue/reactivity@3.0.5/dist/reactivity.global.js" />

这样就可以通过暴露的API使用:

const {effect, ref} = VueReactivity;
function renderer(domString, container){
container.innerHTML = domString;
}
const count = ref(1);

effect(()=>{
renderer(``,document.getElementById("app"))
});
count.value++

渲染器把虚拟DOM节点渲染为真实DOM节点的过程叫做挂载,在Vue中mounted钩子函数会在挂载完成时触发,从而实现虚拟DOM的挂载。此外,渲染器还需要一个挂载点作为参数,用于指定具体的挂载位置,渲染器会将此DOM元素作为容器元素,可以实现内容的渲染。

在Vue.js3中是通过createRenderer函数来创建渲染器renderer,而renderer不仅包含渲染器函数render,还包括服务端渲染使用的hydrate函数。用于创建应用的createApp函数也是渲染器的一部分。

const renderer = createRenderer();
//首次渲染
renderer.render(oldVNode, document.querySelector("#app"));
//第二次渲染
renderer.render(newVNode, document.querySelector("#app"));

在上面代码中,首先调用createRenderer函数创建一个渲染器,通过调用渲染器的renderer.render函数创建新的DOM元素,而后将虚拟DOM节点vnode渲染到挂载点上,这就是挂载。

在同一个挂载DOM上,调用renderer.render函数进行渲染时,渲染器除了实现常规的DOM挂载外,还需要执行页面更新操作,也就是DOM更新。在渲染器会使用vnode与上次渲染的oldVNode进行比较,从而找到并更新变更点,此过程叫做"打补丁"(patch)即更新。

function createRenderer(){
function render(domString, container){
if(vnode){
// 新vnode存在,将其与旧vnode传递给patch函数,进行打补丁
patch(container._vnode, vnode, container);
}else{
if(container._vnode){
// 如果旧节点vnode存在,则需要清空挂载点的DOM元素
container.innerHTML = "";
}
}
// 将vnode存储到container._vnode中
container._vnode = vnode
}
return {
render
}
}

在上面代码中,是render函数的基本实现。patch函数是整个渲染器的核心入口,承载了最重要的渲染逻辑。

patch(n1, n2, container){

}

3、自定义渲染器

我们看看如何自定义实现渲染器,实现跨平台能力,那就从普通的h1标签开始。

const vnode = {
type:"h1",
children:"pingping"
}

在上面代码中实现了一个简单的vnode,使用type属性描述vnode类型,type属性是字符串类型值时是普通标签。

const vnode = {
type:"h1",
children:"pingping"
}
const renderer = createRenderer();
//首次渲染
renderer.render(vnode, document.querySelector("#app"));

这样,我们就可以渲染为为了完成渲染工作,下面可以补充patch函数。

function createRenderer(){
function patch(n1, n2, container){
//如果n1不存在的时候,意味着挂载,需要调用mountElement函数完成挂载
if(!n1){
mountElement(n2, container);
}else{
//n1存在,即打补丁更新DOM节点
}
}
function render(domString, container){
if(vnode){
// 新vnode存在,将其与旧vnode传递给patch函数,进行打补丁
patch(container._vnode, vnode, container);
}else{
if(container._vnode){
// 如果旧节点vnode存在,则需要清空挂载点的DOM元素
container.innerHTML = "";
}
}
// 将vnode存储到container._vnode中
container._vnode = vnode
}
return {
render
}
}

在上面代码中,patch函数中参数n1不存在时,意味着没有旧VNode,此时只需要进行挂载即可。

function mountElement(vnode, container){
const el = document.createElement(vnode.type);
if(typeof vnode.children === "string"){
el.textContent = vnode.children;
}
container.appendChild(el);
}

在上面代码中,简单实现了一个普通标签元素的挂载工作。Vue.js3是个跨平台框架,得益于一个不依赖平台的通用渲染器,而在mountElement函数中依赖了大量浏览器API。想要设计通用渲染器,就必须剥离与平台相关的API,当然可以将这些操作DOM的API作为createRenderer的配置项。

const renderer = createRenderer({
//创建元素
createElement(tag){
return document.createElement(tag);
},
//设置元素的文本节点
setElementText(el, text){
el.textContent = text;
},
//用于给指定父节点添加指定元素
insert(el, parent, achor = null){
parent.insertBefore(el, anchor);
}
})

上面代码中,可以将操作DOM的API封装为一个对象,并把它传递到createRenderer函数,可以通过配置项来取得操作DOM的api。

function createRenderer(options){
const {
createElement,
setElementText,
insert
} = options;
function mountElement(vnode, container){
const el = createElement(vnode.type);
if(typeof vnode.children === "string"){
setElementText(el, vnode.children)
}
insert(el, container);
}
function patch(n1, n2, container){
//...
}
function render(domString, container){
//...
}
return {
render
}
}

现在我们对自定义渲染器有个更深刻的认识,自定义渲染器不是什么黑盒子,只是通过代码抽象,让核心代码不再强依赖于平台特定API,通过自定义配置项实现跨平台。

4、写在最后

在本文中,我们了解到渲染器的作用和实现,知道其是将虚拟DOM转为真实DOM挂载到节点上,在进行节点更新的时候是通过patch实现的。为了实现跨平台渲染,那么就需要用户通过自定义配置项渲染器,从而实现DOM的渲染挂载。

来源:前端一码平川内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯