第7章、渲染器的设计

7.1 渲染器与响应系统的结合

  • 渲染器需要有跨平台的能力。
  • 在浏览器端会渲染为真实的 DOM 元素。
const { effect, ref } = VueReactivity // VueReactivity 是前几章实现的响应式代码

function renderer(domString, container) {
container.innerHTML = domString
}
const count = ref(1)
effect(() => {
renderer(`<h1>${count.value}</h1>`, document.getElementById('app'))
}) count.value++

通过简单的 innerHTML 可以实现渲染器,如果把渲染器放入响应式函数,就可以实现自动渲染。

7.2 渲染器的基本概念

  • renderer 渲染器
  • render 动词 渲染
  • virtual DOM,vdom 虚拟 DOM
  • virtual node,vnode,虚拟 node,构成 vdom 的节点
  • 挂载,mount,虚拟 DOM 渲染为真实 DOM
  • 挂载点,真实 DOM 挂载的位置,一个 DOM 元素,一般用 container 表示。

我们实现 createRenderer 函数,它会创建不同平台的渲染器。其中 render 用于浏览器。渲染分两种情况,挂载和后续渲染(存在旧节点),我们在内部使用 patch 去实现具体渲染(暂未实现)。

function createRenderer() {
// n1 旧node
// n2 新node
// container 容器
// patch可以用户挂载 也可以用于后续渲染
function patch(n1, n2, container) {} function render(vnode, container) {
if (vnode) {
// 如果有新 vnode 就和旧 vnode 一起用 patch 处理
patch(container._vnode, node, container)
} else {
// 没有新 vnode 但是有旧 vnode 直接清空 DOM 即可
if (container._vnode) {
container.innerHTML = ''
}
}
// 把旧 vnode 缓存到 container
container._vnode = vnode
} function hydrate(vnode, container) {
// 服务端渲染
} return {
render,
hydrate,
}
}

7.3 自定义渲染器

把平台相关的函数提取出来,并通过参数传入,然后封装多平台通用的渲染器。

如下,实现了 mountElement 函数,用于 patch 函数在挂载时使用,而挂载要依赖平台的实现,比如创建元素,插入元素,我们把这些通过 options 统一传入。

function createRenderer(options) {
const { createElement, insert, setElementText } = options function mountElement(vnode, container) {
const el = createElement(vnode.type) if (typeof vnode.children === 'string') {
setElementText(el, vnode.children)
}
insert(el, container)
} // n1:旧node,n2:新node,container:容器
function patch(n1, n2, container) {
if (!n1) {
// 挂载
mountElement(n2, container)
} else {
// 打补丁,暂时省略
}
} function render(vnode, container) {
if (vnode) {
// 如果有新 vnode 就和旧 vnode 一起用 patch 处理
patch(container._vnode, vnode, container)
} else {
// 没有新 vnode 但是有旧 vnode 直接清空 DOM 即可
if (container._vnode) {
container.innerHTML = ''
}
}
// 把旧 vnode 缓存到 container
container._vnode = vnode
} function hydrate(vnode, container) {
// 服务端渲染
} return {
render,
hydrate,
}
}

当我们实现浏览器端的渲染器时,可以传入浏览器的 API 实现的函数。

const renderer = createRenderer({
createElement(tag) {
return document.createElement(tag)
},
setElementText(el, text) {
el.textContent = text
},
insert(el, parent, anchor = null) {
parent.insertBefore(el, anchor)
},
}) renderer.render(
{
type: 'h1',
children: 'hello',
},
document.getElementById('app')
)

如上代码,可以在页面渲染出 h1 标签显示 hello。我们也可以通过传入自己实现的对应 API 实现自定义渲染器。

const rendererCustom = createRenderer({
createElement(tag) {
console.log(`创建元素 ${tag}`)
return { tag }
},
setElementText(el, text) {
console.log(`设置 ${JSON.stringify(el)} 的文本内容: ${text}`)
el.text = text
},
insert(el, parent, anchor = null) {
console.log(`将 ${JSON.stringify(el)} 添加到: ${JSON.stringify(parent)} 下`)
parent.children = el
},
}) rendererCustom.render(
{
type: 'h1',
children: 'hello',
},
{ type: 'root' }
)

.

《Vue.js 设计与实现》读书笔记 - 第7章、渲染器的设计的更多相关文章

  1. 【vue.js权威指南】读书笔记(第一章)

    最近在读新书<vue.js权威指南>,一边读,一边把笔记整理下来,方便自己以后温故知新,也希望能把自己的读书心得分享给大家. [第1章:遇见vue.js] vue.js是什么? vue.j ...

  2. 【vue.js权威指南】读书笔记(第二章)

    [第2章:数据绑定] 何为数据绑定?答曰:数据绑定就是将数据和视图相关联,当数据发生变化的时候,可以自动的来更新视图. 数据绑定的语法主要分为以下几个部分: 文本插值:文本插值可以说是最基本的形式了. ...

  3. Linux内核设计与实现 读书笔记 转

    Linux内核设计与实现  读书笔记: http://www.cnblogs.com/wang_yb/tag/linux-kernel/ <深入理解LINUX内存管理> http://bl ...

  4. 【2018.08.13 C与C++基础】C++语言的设计与演化读书笔记

    先占坑 老实说看这本书的时候,有很多地方都很迷糊,但却说不清楚问题到底在哪里,只能和Effective C++联系起来,更深层次的东西就想不到了. 链接: https://blog.csdn.net/ ...

  5. 《Linux内核设计与实现》第八周读书笔记——第四章 进程调度

    <Linux内核设计与实现>第八周读书笔记——第四章 进程调度 第4章 进程调度35 调度程序负责决定将哪个进程投入运行,何时运行以及运行多长时间,进程调度程序可看做在可运行态进程之间分配 ...

  6. 《Linux内核设计与分析》第六周读书笔记——第三章

    <Linux内核设计与实现>第六周读书笔记——第三章 20135301张忻估算学习时间:共2.5小时读书:2.0代码:0作业:0博客:0.5实际学习时间:共3.0小时读书:2.0代码:0作 ...

  7. 《LINUX内核设计与实现》第三周读书笔记——第一二章

    <Linux内核设计与实现>读书笔记--第一二章 20135301张忻 估算学习时间:共2小时 读书:1.5 代码:0 作业:0 博客:0.5 实际学习时间:共2.5小时 读书:2.0 代 ...

  8. 《Linux内核设计与实现》第四周读书笔记——第五章

    <Linux内核设计与实现>第四周读书笔记--第五章 20135301张忻 估算学习时间:共1.5小时 读书:1.0 代码:0 作业:0 博客:0.5 实际学习时间:共2.0小时 读书:1 ...

  9. 《Linux内核设计与实现》第五周读书笔记——第十一章

    <Linux内核设计与实现>第五周读书笔记——第十一章 20135301张忻 估算学习时间:共2.5小时 读书:2.0 代码:0 作业:0 博客:0.5 实际学习时间:共3.0小时 读书: ...

  10. 《Linux内核设计与实现》读书笔记——第五章

    <Linux内核设计与实现>读书笔记--第五章 标签(空格分隔): 20135321余佳源 第五章 系统调用 操作系统中,内核提供了用户进程与内核进行交互的一组接口.这些接口让应用程序受限 ...

随机推荐

  1. QT 开发快速入门

    本人 qt 业余,但有的时候要用到 qt,而又没有系统的学习,用到哪里看哪里. 环境: vs2012+ qt-vsaddins+qt5.5 qt 的按钮点击事件出发的基本要素: 1. 按钮触发函数为 ...

  2. Beizer。。。。。

    <html> <head>AS</head> <script> var cvs; var context; //context.fill();//填充 ...

  3. Linux 中 Crontab 执行时的环境变量问题(allure命令不执行)

    前几天做了UI自动化脚本部署linux服务器,但是放下脚本的allure命令不执行(生成allure报告和启动allure服务的命令不执行),然后就各种找问题,一开始怀疑是allure的环境变量问题, ...

  4. 【Tutorial C】04 基本输入输出

    输出单个字符 putchar('a'); // 字符输出函数,其功能是在终端(显示器)输出单个字符. putchar('\n'); // 支持转义换行 putchar(77); // 可以直接注入AS ...

  5. 【JavaScript】文件上传下载问题

    问题原因 一般文件上传前端甚至可以不涉及JS来实现 input标签套在form标签,由form标签直接发送请求就可以实现上传功能 但是现在很多项目都使用前后端分离,AJAX一刀切所有. input标签 ...

  6. 【Spring-Security】Re06 自定义Access & 注解权限分配

    一.基于ACCESS方法处理的实现: 我们之前使用的任何放行规则的方法,本质上还是调用access方法执行的 这也意味之我们可以直接使用access方法去方向,只需要注入不同的字符串即可 自定义Acc ...

  7. 国内的开源AI模型共享网站(AI模型的GitHub)—— mindscope —— 使用git lfs方式下载模型文件

    参考前文: 国内的开源AI模型共享网站(AI模型的GitHub)-- mindscope -- 对标外网的"huggingface",mindscope好用吗? 使用git lfs ...

  8. Python示例——负数的位运算

    平时在coding的时候虽然会遇到位运算但一般也都是正数的位运算,今天突然见到了使用负数的位运算,对此十分好奇和困惑,为此做了下了解,于是有了此文. 给出一些位运算的例子: 其中,正数的位运算是最为常 ...

  9. .NET 屏幕录制

    窗口/屏幕截图适用于截图.批注等工具场景,时时获取窗口/屏幕图像数据流呢,下面讲下视频会议共享桌面.远程桌面这些场景是如何实现画面录制的. 常见的屏幕画面时时采集方案,主要有GDI.WGC.DXGI. ...

  10. SQL Server序列号的获取

    建表: 1 USE [JX_IMS_CPK] 2 GO 3 4 SET ANSI_NULLS ON 5 GO 6 7 SET QUOTED_IDENTIFIER ON 8 GO 9 10 CREATE ...