vue3源码(六)渲染原理-runtime-dom

1、从入口文件看实现

项目入口文件

import { createApp } from 'vue'
import './style.css'
import App from './App.vue'createApp(App).mount('#app')

文件位置core\packages\runtime-dom\src\index.ts
在这里插入图片描述
保证了render唯一性

// // rendererOptions 是patchProp 和nodeOps的合集,包含了dom操作和节点对比方法
const rendererOptions = /*#__PURE__*/ extend({ patchProp }, nodeOps)function ensureRenderer() {return (renderer ||(renderer = createRenderer<Node, Element | ShadowRoot>(rendererOptions)))
}

createApp中主要调用了ensureRenderer创建返回的App,ensureRenderer中返回createRenderer
createRenderer核心方法baseCreateRenderer 主要包含了创建渲染器和更新和渲染的一系列方法,接下来开始从使用到实现吧~

2、两种渲染器的使用

 import { createRenderer ,render,h} from "/node_modules/@vue/runtime-dom/dist/runtime-dom.esm-browser.js";// 1、createRenderer 我们可以自己创建渲染器(自己提供渲染方式)// 2、render 内置的渲染器 (渲染dom元素)// 3、h 方法可以创建一个虚拟dom (type,propsOrChildren,children)console.log(createRenderer,render,h);let  ele = h("h1","hello render")// render(ele,app)  用提供的api去渲染// 自定义渲染器const renderer = createRenderer({// 创建一个节点createElement(type){return document.createElement(type)},// 节点的展示setElementText(el,text){el.textContent = text},// 节点内容insert(el,container){container.appendChild(el)}})renderer.render(ele,app)// runtime-dom 提供一系列操作dom的API// @vue/runtime-dom是针对浏览器的  --> @vue/runtime-core 是跨平台的  --> @vue/reactivity 

3、renderOptions实现

renderOptions主要包含两个部分:

  • dom节点的操作
  • 属性的操作
const renderOptions = Object.assign({ patchProp }, nodeOps);
export { renderOptions };

3.1 nodeOps

export const nodeOps = {insert: (child, parent, anchor) => {// 添加节点parent.insertBefore(child, anchor || null);},remove: (child) => {// 节点删除const parent = child.parentNode;parent && parent.removeChild(child);},createElement: (tag) => document.createElement(tag), // 创建节点createText: (text) => document.createTextNode(text), // 创建文本setText: (node, text) => (node.nodeValue = text), //  设置文本节点内容setElementText: (el, text) => (el.textContent = text), // 设置文本元素中的内容parentNode: (node) => node.parentNode, // 父亲节点nextSibling: (node) => node.nextSibling, // 下一个节点querySelector: (selector) => document.querySelector(selector), // 搜索元素
};

3.2 patchProp

export default function patchProp(el, key, prevValue, nextValue) {if (key === "class") {return patchClass(el, nextValue);} else if (key === "style") {return patchStyle(el, prevValue, nextValue);} else if (/^on[^a-z]/.test(key)) {return patchEvent(el, key, nextValue);}else{return patchAttr(el, key, nextValue)}
}

3.2.1 patchClass

export default function patchClass(el, value) {if (value) {el.className = value;} else {el.removeAttribute("class");}
}

3.2.2 patchStyle

export default function patchStyle(el, prevValue, nextValue) {let style = el.style;// 把新的加进来for (let key in nextValue) {style[key] = nextValue[key];}// 把多余的删掉if (prevValue) {for (let key in prevValue) {if (nextValue[key] == null) {style[key] = null;}}}
}

3.2.3 patchEvent

// 创建一个调用器,执行value值,value可以改变
function createInvoker(value) {const invoker = (e) => invoker.value();invoker.value = value; // 修改value可以修改方法对应的调用函数return invoker;
}export default function patchEvent(el, name, nextValue) {const invokers = el._vei || (el._vei = {});const eventName = name.slice(2).toLowerCase();const existingInvoker = invokers[name];//   如果之前存在同名方法 则修改函数if (nextValue && existingInvoker) {return (existingInvoker.value = nextValue);}if (nextValue) {// 如果之前没有同名方法, 则给方法赋值const invoker = (invokers[name] = createInvoker(nextValue));return el.addEventListener(eventName, invoker);}if (existingInvoker && !nextValue) {el.removeEventListener(eventName);invokers[name] = undefined;}
}

3.2.4 patchAttr

export default function patchAttr(el,key, value) {if (value) {el.setAttribute(key, value);} else {el.removeAttribute(key)}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/39623.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

可视化低代码平台之:RayData光启元的震撼作品。

RayData家的可视化作品&#xff0c;贝格前端工场是经常碰到&#xff0c;制作十分的精良&#xff0c;业内很有影响力。他们也有自己的低代码平台&#xff0c;分为了桌面版和网页版&#xff0c;本期分享一下他们的作品。

彻底掌握 Git:从零基础到高级实战的全方位教程

文章目录 一、Git 简介二、安装 Git1. Windows2. macOS3. Linux 三、Git 基本概念四、初次使用 Git1. 配置 Git2. 创建一个新的 Git 仓库3. 克隆一个远程仓库4. 跟踪文件5. 提交变更6. 查看历史记录 五、Git 分支管理1. 创建和切换分支2. 合并分支3. 分支冲突 六、远程仓库1. 添…

to_json 出现乱码的解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

国产分布式数据库灾备高可用实现

最近在进行核心业务系统的切换演练测试&#xff0c;就在想一个最佳的分布式数据库高可用部署方案是如何保证数据不丢、系统可用的&#xff0c;做到故障时候可切换、可回切&#xff0c;并且业务数据的一致性。本文简要介绍了OceanBase数据库和GoldenDB数据库在灾备高可用的部署方…

kafka的架构

一、架构图 Broker&#xff1a;一台 kafka 服务器就是一个 broker。一个kakfa集群由多个 broker 组成。一个 broker 可以容纳多个 topic。 Producer&#xff1a;消息生产者&#xff0c;就是向 kafka broker 发消息的客户端 Consumer&#xff1a;消息消费者&#xff0c;向 kafk…

深海电波,智能驾驭:海上发电系统中的先进网关技术

随着技术的不断演进&#xff0c;海上风电场逐渐走向深海&#xff0c;随之而来的高速通信保障成为一大难题。同时&#xff0c;海上风电特殊的环境与部署技术&#xff0c;也给运维带来了作业难、成本高、响应慢等困难。通过在沿海岸边建立高站&#xff0c;结合超远覆盖、载波聚合…

springboot java.lang.ClassNotFoundException: dm.jdbc.driver.DmDriver 应该如何解决

遇到的问题&#xff1a;项目中引用了外部的达梦jar包 在idea中正常使用 也能找到dm.jdbc.driver.DmDriver 驱动 但是当通过jenkins 构建部署到服务器上 总是报 ClassNotFoundException: dm.jdbc.driver.DmDriver 找不到驱动 应用到的驱动代码如下格式 排查步骤 1.首先看你的项…

ROS2仿真工具-gazebo

gazebo独立于ROS2&#xff0c;就像插件一样&#xff0c;需要安装。 1.安装 sudo apt install gazebo sudo apt install ros-humble-gazebo-* 2.运行测试demo gazebo /opt/ros/humble/share/gazebo_plugins/worlds/gazebo_ros_diff_drive_demo.world 查看所有话题 ros2 top…

使用css做一个旋转的八卦图

使用css做一个旋转的八卦图 1, html部分 <div class"tai"><div class"bai"></div><div class"hei"></div> </div>2, css部分 .tai{width: 200px;height: 200px;border: 1px solid #000;background: linea…

STM32-I2C硬件外设

本博文建议与我上一篇I2C 通信协议​​​​​​共同理解 合成一套关于I2C软硬件体系 STM32内部集成了硬件I2C收发电路&#xff0c;可以由硬件自动执行时钟生成、起始终止条件生成、应答位收发、数据收发等功能&#xff0c;减轻CPU的负担 特点&#xff1a; 多主机功能&#x…

Shiro框架

入门概述 1 shiro是什么? Apache Shiro 是一个功能强大且易于使用的 Java 安全(权限)框架。Shiro 可以完成&#xff1a;认证、授权、加密、会话管理、与 Web 集成、缓存 等。借助 Shiro 您可以快速轻松地保护任何应用程序——从最小的移动应用程序到最大的 Web 和企业应用程…

计算机网络网络层复习题1

一. 单选题&#xff08;共27题&#xff09; 1. (单选题)以太网 MAC 地址、IPv4 地址、IPv6 地址的地址空间大小分别是&#xff08; &#xff09;。 A. 2^48&#xff0c;2^32&#xff0c;2^128B. 2^32&#xff0c;2^32&#xff0c;2^96C. 2^16&#xff0c;2^56&#xff0c;2^6…

浅谈k8s中cni0和docker0的关系和区别

最近在复习k8s网络方面的知识&#xff0c;查看之前学习时整理的笔记和文档还有过往自己总结的博客之后发现一个问题&#xff0c;就是在有关flannel和calico这两个k8s网络插件的文章和博客中&#xff0c;会涉及到cni0和docker0这两个网桥设备&#xff0c;但是都没有明确说明他们…

C# WPF自制批注工具(方便标记重点和演示)

在教学和演示中&#xff0c;我们通常需要对重点进行批注&#xff0c;下载安装第三方工具批注显得很麻烦。本篇使用WPF开发了一个批注工具&#xff0c;工具小巧&#xff0c;功能丰富&#xff0c;非常使用日常免费使用&#xff0c;或者进行再次开发。 自制批注工具具有以下功能特…

Flask 数据创建时出错

当我们在使用 Flask 创建数据时遇到错误&#xff0c;可能有多种原因&#xff0c;包括代码错误、数据库配置问题或依赖项错误。具体情况我会总结成一篇文章记录下&#xff0c;主要是归类总结一些常见的解决方法和调试步骤&#xff0c;帮助大家解决问题&#xff1a; 1、问题背景 …

OFDM技术概述8——FBMC

Filter bank multicarrier(FBMC&#xff0c;滤波器组多载波)&#xff0c;是一种类似于OFDM的调制方式&#xff0c;用滤波器抑制子载波的旁瓣大小&#xff0c;使用FFT/IFFT或多相滤波器实现&#xff0c;其应用于5G的主要优势&#xff1a; 子载波信号带限&#xff0c;带外泄漏小…

LiveNVR监控流媒体Onvif/RTSP用户手册-视频广场:状态记录、播放、回放入口、筛选在线离线、搜索

LiveNVR监控流媒体Onvif/RTSP用户手册-视频广场:状态记录、播放、回放入口、筛选在线离线、搜索 1、视频广场1.1、搜索筛选1.2、状态记录1.3、播放1.4、视频信息1.5、回放入口 2、RTSP/HLS/FLV/RTMP拉流Onvif流媒体服务 1、视频广场 1.1、搜索筛选 可以下拉筛选 在线、离线 &a…

C++部分复习笔记上

C语法复习 1. C入门基础 缺省参数 半缺省参数必须从右往左依次来给出&#xff0c;不能间隔着给缺省参数不能在函数声明和定义中同时出现缺省值必须是常量或者全局变量C语言不支持&#xff08;编译器不支持&#xff09; 函数重载 函数重载是函数的一种特殊情况&#xff0c;…

William Yang:从区块链先锋到艺术平台创始人

在区块链技术和加密货币市场飞速发展的今天&#xff0c;William Yang无疑是这一领域的佼佼者。他不仅在学术和媒体领域取得了显著成就&#xff0c;更在创业之路上不断探索&#xff0c;成为了业内知名的KOL&#xff08;关键意见领袖&#xff09;。今天&#xff0c;我们有幸采访到…

AI姓氏头像生成微信小程序系统源码

&#x1f525;【科技新潮流】AI姓氏头像生成系统&#xff0c;你的专属个性新名片&#xff01;&#x1f389; &#x1f31f; 开篇惊艳&#xff1a;一键解锁你的姓氏魅力 ✨ Hey小伙伴们&#xff0c;今天我要安利一个超酷炫的科技小玩意——AI姓氏头像生成系统&#xff01;是不…