1.0 Vue的编译和运行

news/2024/10/18 7:46:35/

1、编程范式:命令式和声明式

编程范式是指一种程序语言的代码风格、样式,每一种范式都包含了代码特征和结构,以及处理错误的方式。

例如现在需要实现生成一个div模块,其显示的文本内容为hello world,添加一个点击事件。那么实现这个功能可以通过命令式和声明式两种方式来编写。

命令式代码示例如下:

// 创建一个div标签
const div = document.createElement("div")
// 设置其文本内容为hello world
div.textContent = "hello world"
// 设置点击事件
div.addEventListener('click', () => {alert("ok")})

声明式代码示例如下:

<div @click="() => {alert('ok')}">hello world</div>
  1. 命令式:直接一步一步命令计算机,每一步执行任务。
  2. 声明式:直接声明结果,至于执行的过程并不关心。

以上的两种方法其实我们在日常的代码编写中都经常用到,但是很少去思考这两种范式的实现优缺点。

首先明确的是命令式的运行效率一定是高于声明式的,对于命令式代码来说浏览器是可以直接执行的,这是原生的JavaScript代码,但是对于声明式来说它需要更多的步骤来处理,然后被执行。声明式的代码首先需要被编译处理,他会被处理成一个JavaScript的对象,然后渲染这个对象。

同样在修改文本内容的时候体现得非常的清晰,改变文本内容对于命令式代码十分简单迅捷,即div.textContent="change content",这就是最快的修改,没有更快了。对于声明式代码来说需要找到其编译后生成的对象(见下文虚拟DOM),然后再从对象中找出不同的地方,进行修改,然后重新渲染。

其实在项目开发中都是选择使用声明式代码,原因很简单,虽然命令式代码执行快,逻辑流程清晰,但是它对于心智的负担太大了,这需要我们做JavaScript原生的代码编写。声明式则逻辑简单很多,一个一个标签,无论是嵌套还是并行都体现得十分清晰。

这也是Vue为什么如此火的原因之一,因为它做了大量的声明式命令的封装,对于用户来说它和HTML一样的声明范式入手很快,并且它的性能也很好(之后会介绍),它做到了在心智负担和性能之间的很好平衡。

2、什么是虚拟DOM及其性能

虚拟DOM就是使用一个JavaScript对象来描述一个真实DOM。
声明式代码在修改的时候有两种方法,第一种是直接重新建立然后渲染,第二种是找出不同的地方,然后针对不同的地方替换掉。
第一种方法如innerHTML,代码如下:

// 当需要修改时需要修改html,然后重新赋值
const html = `
<div @click="() => {alert('ok')}">hello world</div>
`
div.innerHTML = html

第二种方式就是使用JavaScript对象来描述,然后针对对象进行差异化比较(Diff的内容见后文),然后渲染不同的地方,比如

obj = {tag: "div",children: [{tag: "div", children: "hello world"}]
}

此时的obj对象就是一个虚拟DOM。

看似第一种方式消耗不大,其实innerHTML文本需要被解析,哪怕只有一个字符修改了,整个innerHTML都需要被重新构建,然后解析,这在DOM层面需要销毁所有的节点,然后再重新创建。在真实DOM层面操作这远比JavaScript的运行消耗的时间长。

所以虚拟DOM存在的意义就是将很多需要在真实DOM的操作在虚拟DOM优化,上面讲述了命令式效率一定是高于声明式的效率的,但是我们可以尽量让声明式的效率贴近命令式。

对于虚拟DOM只需要一个渲染函数就可以将虚拟DOM渲染成真实DOM,如:

function Render(obj, root) {// 根据节点类型创建节点const el = document.createElement(obj.tag)// 如果是文本节点直接创建if(typeof obj.child === 'string') {const text = document.createTextNode(obj.child)el.appendChild(text)} else if(obj.child) {// 如果有子节点则递归创建obj.children.forEach((child) => {Render(child, el)})}root.appendChild(el)
}

所以在声明式代码在执行时有以下步骤:

  1. 编译(标签 To 对象)
  2. 运行(渲染对象)

流程如下:

在这里插入图片描述

其实有个问题就是为什么不直接从声明式代码编译成真实DOM的执行语句:
在这里插入图片描述

这样的就省略了运行的过程,直接编译完成就行了。以上所述的是纯编译框架,如Svelte就是纯编译的,但是Vue是运行+编译的过程,这是因为Vue在运行时做了很多处理,其性能甚至不输纯编译的框架,这在后面会讲解。


http://www.ppmy.cn/news/58376.html

相关文章

【Python百日进阶-Web开发-Feffery】Day613- 趣味Dash_13:PDF转换中心的项目优化

文章目录 一、环境准备1.1 初始化基础`Python + Dash`环境1.2 本项目中需要增加的第三方包二、本项目B站视频讲解三、页面效果四、项目源码一、环境准备 1.1 初始化基础Python + Dash环境 CSDN文档参见:https://blog.csdn.net/yuetaope/article/details/129795264 Bilibili视…

让语言学习更简单的 WordFlow

作为一个英语并不是那么特别好的计算机专业学生&#xff0c;长期积累英语的学习对个人发展还是有意义的。简单来说&#xff0c;我在语言上最大的两个问题&#xff0c;一个自己「不理解」&#xff0c;另一个是自己「不会表达」。 上述两个问题主要体现在口语层面&#xff0c;而…

R语言的贝叶斯时空数据模型

时间&#xff0d;空间数据&#xff08;以下简称“时空数据”&#xff09;是最重要的观测数据形式之一&#xff0c;很多科学研究的数据都以时空数据的形式得以呈现&#xff0c;而科学研究目的可以归结为挖掘时空数据中的规律。另一方面&#xff0c;贝叶斯统计学作为与传统统计学…

面向对象和面向过程的区别

编程语言分析 C语言C部分面向对象和部分面向过程Java面向对象 面向过程 面向过程注重解决问题的步骤&#xff0c;第一步干什么&#xff0c;第二步干什么面向过程注重因果关系&#xff0c;因为A所以B。面向对象注重过程和与实现步骤 面向过程的缺点 代码耦合度过高&#xff…

Packet Tracer - 配置 IPv6 静态路由和默认路由

Packet Tracer - 配置 IPv6 静态路由和默认路由 IPv6 地址分配表 设备 接口 IPv6 地址/前缀 默认网关 R1 G0/0 2001:DB8:1:1::1/64 不适用 S0/0/0 2001:DB8:1:A001::1/64 不适用 R2 G0/0 2001:DB8:1:2::1/64 不适用 S0/0/0 2001:DB8:1:A001::2/64 不适用 S0…

B站java、计算机学习整理(菜鸟版本)

B站java、计算机学习整理&#xff08;菜鸟版本&#xff09; 简介1、入门篇2、工具篇3、数据库篇4、框架篇5、JVM 篇6、源码篇7、算法与数据结构8、操作系统9、计算机组成原理10、计算机网络11、 设计模式 简介 处在互联网时代&#xff0c;是一种幸福&#xff0c;因为各式各样的…

Oracle系列之六:Oracle表分区

Oracle表分区 1. 基本概念2. 范围分区3. Hash分区&#xff08;散列分区&#xff09;3. 复合分区 1. 基本概念 Oracle表分区是将一个大型表分割成更小、更易于管理的部分的技术。分区后的表被称为分区表&#xff0c;其中每个分区都可以独立地进行维护、管理和查询。表分区可基于…

SpringCloud:ElasticSearch之集群

单机的elasticsearch做数据存储&#xff0c;必然面临两个问题&#xff1a;海量数据存储问题、单点故障问题。 海量数据存储问题&#xff1a;将索引库从逻辑上拆分为N个分片&#xff08;shard&#xff09;&#xff0c;存储到多个节点单点故障问题&#xff1a;将分片数据在不同节…