2.0 Vue框架设计的核心要素
本章主要讲解,一个好的框架在构建的时候,需要考虑到的要素,包含报错信息反馈、警告信息反馈、减少打包体积、良好的输出、特性开关(兼容)等
1、提升用户开发体验
提升用户开发体验主要体现在用户使用框架进行开发时,框架能够提供良好的交互体验,如及时的警告。这在Vue.js中做的很好,在源码中可以看到各个部分都有很多的warn函数的调用,并且在warn函数中尽可能提供了有用信息。
并且Vue.js支持使用自定义的打印数据,比如当打印reacitve或者ref时打印出的信息并不直观。打印const value = ref(0)中value的值时,打印结果为:

为了解决这一问题,Vue.js可以通过DevTools更改其Console选项设定合适的输出结果。
2、控制框架代码的体积
在保证功能完善的情况下肯定是使用的代码越少越好,但是根据上述情况为了提升开发者体验加入了很多警告信息,这些信息会让代码体积增多。
其实做过项目开发者都知道,在项目中分为开发者模式和生产模式。根据不同的模式削减代码以控制代码体积,比如警告信息只会出现在开发者模式之下。所以在Vue.js的源码中所有的warn信息都加入了控制的字段。
if(__DEV__ && !res) {warn(// 警告信息)
}
这里的__DEV__只有在开发模式之下会被替换成字面量true,所以在非开发模式下上面的警告部分的代码就会变成dead code,在最后打包输出的时候被移除。
这样就做到了友好的开发,并且在生成环境下不会产生冗余代码。
3、框架做到良好的Tree-Shaking
Tree-Shaking就是将项目中永远不会执行的代码打包时删去,如上所说的警告信息在生产环境下属于dead code在打包的时候需要被去除,那么怎么区分代码是否会被执行呢。
要使用Tree-Shaking那么模块必须是ESM(ES Module),因为Tree-Shaking依赖ESM的静态结构。对于ESM来说模块是静态引入的,可以不依靠运行程序进行分析,即所谓的静态分析。
在打包时根据入口文件无法到达的代码会被舍弃。同时如果一个函数有副作用那么这个函数也是不会被删去的,比如:
const data = {value: 1} let getCount = 0
// 副作用函数,计数value被获取的次数,修改全局遍历getCount
function countAdd(target, key) {getCount += 1
}
// 对data对象进行代理
const obj = new Proxy(data, {get(target, key) {// 在获取value的时候执行副作用函数countAdd(target, key)return target[key]}
})console.log(obj.value)
此时函数countAdd在执行时会改变变量getCount的值,即这个函数产生了副作用,所以这个函数是不属于dead code。
函数产生副作用其实是相对于纯函数来说的,纯函数的定义需同时满足以下两条:
- 函数在输入相同的情况下总可以得到相同的输出,即该函数的运行并不会依赖于任何外部的数据。
- 函数在运行过程中并不会导致外部数据变化,即不会产生副作用。
其实上述函数产生副作用的就是对是不是纯函数的判定,只要满足以上两个条件即为纯函数。在Vue框架内可以在函数的前面加注释/*# __PURE__*/来对其进行Tree-Shaking。这在Vue.js3源码中可以看到很多这样的函数注释。
4、特性开关
在Vue的框架设计中会设计很多的特性(功能),同时在框架迭代的过程中也会产生很多的遗留API,这些功能在一个项目中可能不会完全用到,或者随着框架越来越臃肿打包体积会越来越大。所以一个良好的框架肯定会对相应的功能设置特性开关,将不需要的功能关掉,在打包的时候忽略掉,减少打包的体积。
特性开关的功能实现也和上文提到的__DEV__常量一样,给这些功能设定一个一个的常量,通过给常量赋值来决定功能是否开启。
比如在Vue2中我们使用的是选项型API,其data、methods、computed…是区分开来的:
export default {data() {}, //data选项computed() {}, //computed选项// 其他选项
}
而在Vue3中使用的是组合型API,其代码结构可以根据功能划分,如:
export default {setup() {const count = ref(1)const doubleCount = computed(() => count.value * 2)// 其他功能代码}
}
在Vue3中其实我们也是可以使用选项型API的,根据__VUE_OPTIONS_API__开关来开闭该特性,这是理解特性开关一个很好的例子。
其实Vue3选择使用组合型API的好处很多,大家最常说的是后期维护和大页面编写更加的友善了,因为之前的选项型API需要把数据放一部分,函数放一部分…根据类型来做区分,在后面需要对相应功能修改的时候需要滑上滑下地寻找,而选项型API可以把相应的功能代码放在一块,代码定位更加简单。
其实组合型API的改变更多的是一种思维上的变化,从关注数据到关注功能,这样以功能为核心可以更加的灵活,对于相同功能的代码复用,嵌套等更加轻松灵活。
5、报错处理
无论在什么框架中报错处理都是一个十分重要的环节,框架错误处理机制决定了用户程序的健壮性,同时好的报错处理机制也减少了开发者的心智负担。
假设我们有一个函数,接收一个回调函数,然后执行该回调函数,简单可以这样写:
function foo(fn) {fn && fn()
}
此时如果用户提供的回调函数出错怎么办?其实可以使用try…catch捕获
function foo(fn) {try {fn && fn()} catch(e) {console.log(e)}
}
但是有个问题,比如我们现在有很多个工具函数,都是接受回调函数,然后执行,那么全部使用try…catch是十分臃肿的,那么进一步可以封装出一个报错的函数。
// 统一报错函数
function callWithEroorHandling(fn) {try {fn && fn()} catch(e) {console.log(e)}
}
//这里直接调用
function foo(fn) {callWithEroorHandling(fn)
}
function bar(fn) {callWithEroorHandling(fn)
}
将报错处理部分单独提出来,统一处理:
let handleError = null
function registerErrorHandle(fn) {handleError = fn
}
function callWithEroorHandling(fn) {// 执行程序try {fn && fn()} catch(e) {// 报错后给注册的报错处理函数handleError(e)}
}
// 注册报错之后的处理
registerErrorHandle((e) => {console.log("注册报错!")console.log(e)
})
相关文章:
2.0 Vue框架设计的核心要素
本章主要讲解,一个好的框架在构建的时候,需要考虑到的要素,包含报错信息反馈、警告信息反馈、减少打包体积、良好的输出、特性开关(兼容)等 1、提升用户开发体验 提升用户开发体验主要体现在用户使用框架进行开发时&…...
“智慧赋能 强链塑链”——精细化工行业仓储物流数字化转型探讨
精细化工行业作为衡量国家化学工业水平高低的重要标志,为国民经济提供重要的终端产品支持,相比较大化工产品,精细化工产品需要高度专业技能和工艺,其生产过程需要复杂的化学反应,以及严格的控制条件,产出的…...
用DG备库做的rman备份恢复一个数据库
环境描述: 1.因为主库存储空间不足,于是将备份放在dg备库上做。 2.主库因为磁盘空间问题,数据文件有两个目录。 3.dg备库因为主库两个数据文件目录里面有两个同名数据文件,所有dg备库也有两个数据文件目录。 4.主库与备库与测…...
JAVA中的IO操作有哪些?
在Java编程语言中,输入/输出(IO)操作是很重要的部分,它允许程序从外部系统读取数据,或将数据输出到外部系统。Java提供了一组强大的IO类库,可以让开发人员方便地进行各种IO操作。 Java中的IO操作可以分为两…...
10:00面试,10:04就出来了 ,问的实在是太...
从外包出来,没想到竟然死在了另一家厂子 自从加入这家公司,每天都在加班,钱倒是给的不少,所以我也就忍了。没想到12月一纸通知,所有人都不许加班,薪资直降30%,顿时有吃不起饭的赶脚。 好在有个…...
wangzherongyao PMO
感谢【五一节】大家的相遇,总结下。 2023年05月02日,【第一组】组队开黑 我总结了下这天为什么打的那么好,首先赛季初段位在王者附近,大家心态重视程度也高,不轻敌,也不盲目,运营好兵线一步一步…...
Dart语法上
一、Dart介绍及环境 1.1 Dart介绍: Dart是由谷歌开发的计算机编程语言,它可以被用于web、服务器、移动应用 和物联网等领域的开发。Dart诞生于2011年,号称要取代JavaScript。但是过去的几年中一直不温不火。直到Flutter的出现现在被人们重新重视。 要学…...
SignOff Criteria——POCV(Parametric OCV) introduction
文章目录 1. O v e r v i e w Overview Overview2. P O C V A n a l y s i s POCV\ Analysis POCV Analysis3. P O C V F l o w POCV\ Flow POCV Flow4. P O C V R e p o r t POCV\ Report POCV Report 1. O v e r v i e w Overview Overview P r o c e s s v a r i a t i…...
Android 内存分析(java/native heap内存、虚拟内存、处理器内存 )
1.jvm 堆内存(dalvik 堆内存) 不同手机中app进程的 jvm 堆内存是不同的,因厂商在出厂设备时会自定义设置其峰值。比如,在Android Studio 创建模拟器时,会设置jvm heap 默认384m , 如下图所示: 当app 进程中java 层 new 对象(加起来总和)占用…...
产品思维与工程师思维
目录标题 什么是产品思维用户痛点体验价值 产品思维与工程师思维有什么区别?产品需要什么能力洞察需求的能力逻辑思维能力成本意识 场景化思维和用户体验数据分析和售后服务数据分析服务大多数用户原则 什么是产品思维 产品思维就是考虑产品的方方面面,…...
Android---启动速度优化
App 启动流程 1. 点击桌面 App 图标,Launcher 进程采用 Binder IPC 向 system_server 进程发起 startActivity 请求 ; 2. system_server 进程接收到请求后,向 zygote 进程发送创建进程的请求; 3. zygote 进程 fork 出新的子进程…...
使用 Mercury 直接从 Jupyter 构建 Web 程序
动动发财的小手,点个赞吧! 有效的沟通在所有数据驱动的项目中都至关重要。数据专业人员通常需要将他们的发现和见解传达给利益相关者,包括业务领导、技术团队和其他数据科学家。 虽然传达数据见解的传统方法(如 PowerPoint 演示文…...
Python基础(二)
目录 一、类型转换 1、为什么需要数据类型转换 2、数据类型转化的函数 3、str()函数类型转换使用 4、int()函数类型转换使用 4.1int()不能将str类型数据转换成int 4.2int()将bool类型转换成int 4.3int()将float转换成int 5、Float()函数类型转换使用 5.1Float()函数不…...
第41讲:Python循环语句中的break-else语法结构
文章目录 1.在循环正常结束后执行动作的思路2.通过控制布尔值变量的方式在循环正常结束后执行某些操作2.1.while循环语句2.2.for-in循环语句3.通过else从句来执行某些操作1.在循环正常结束后执行动作的思路 在执行while循环语句或者for循环语句时,如果循环是正常结束的,非执…...
双系统-真机安装ubuntu
服务器系统最好选择legacy启动mbr硬盘,数据盘可以使用gpt格式,超过2t的只能用gpt。 华为2288v3用uefi找不到启动硬盘,或者是找到硬盘后无法引导,迁移系统得到有efi引导文件的硬盘也不行,选择用legacy吧。 ubuntu默认uefi启动,若使用legacy,则需要easybcd处理一下引导。 …...
Android实现向facebook回复消息代码
以下是一个示例代码,它基于Facebook SDK版本5.0,具体实现如下: 1. 集成Facebook SDK库 下载Facebook SDK并将其加入到Android Gradle构建文件中,像这样: groovy dependencies { implementation com.facebook.an…...
IDEA小技巧-Git的回滚强推代码找回
标题IDEA小技巧-Git的回滚&&强推&&代码找回 本地未Commit 新增文件 delete 变更文件 rollback 第一种方式 第二种方式 切换默认变更列表 Commit未push undo commit 仅适用于最后一次的提交进行回滚 drop commit 回滚 revert commit revert commi…...
即时通讯为什么不采用UDP的连接方式呢
即时通讯为什么不采用UDP的连接方式呢 博主今天从网络上找了几个比较关注的热点的内容进行讲解 1.首先介绍一下UDP连接的缺点 不可靠:UDP是一种无连接的传输协议,它不提供数据包的可靠传输保证。这意味着当使用UDP进行通信时,数据包可能会丢…...
二叉树(纲领篇)
文档阅读 文档阅读 二叉树解题的思维模式分两类: 1、是否可以通过遍历一遍二叉树得到答案?如果可以,用一个 traverse 函数配合外部变量来实现,这叫「遍历」的思维模式。 2、是否可以定义一个递归函数,通过子问题&a…...
day41—选择题
文章目录 1.某主机的IP 地址为 180.80.77.55,子网掩码为 255.255.252.0。若该主机向其所在子网发送广播分组,则目的地址可以是(D)2.ARP 协议的功能是(A)3.以太网的MAC 协议提供的是(A࿰…...
linux之kylin系统nginx的安装
一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源(HTML/CSS/图片等),响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址,提高安全性 3.负载均衡服务器 支持多种策略分发流量…...
从零实现富文本编辑器#5-编辑器选区模型的状态结构表达
先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...
镜像里切换为普通用户
如果你登录远程虚拟机默认就是 root 用户,但你不希望用 root 权限运行 ns-3(这是对的,ns3 工具会拒绝 root),你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案:创建非 roo…...
Keil 中设置 STM32 Flash 和 RAM 地址详解
文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...
MySQL 8.0 OCP 英文题库解析(十三)
Oracle 为庆祝 MySQL 30 周年,截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始,将英文题库免费公布出来,并进行解析,帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...
tree 树组件大数据卡顿问题优化
问题背景 项目中有用到树组件用来做文件目录,但是由于这个树组件的节点越来越多,导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多,导致的浏览器卡顿,这里很明显就需要用到虚拟列表的技术&…...
Go 语言并发编程基础:无缓冲与有缓冲通道
在上一章节中,我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道,它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好࿰…...
vulnyx Blogger writeup
信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面,gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress,说明目标所使用的cms是wordpress,访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...
MacOS下Homebrew国内镜像加速指南(2025最新国内镜像加速)
macos brew国内镜像加速方法 brew install 加速formula.jws.json下载慢加速 🍺 最新版brew安装慢到怀疑人生?别怕,教你轻松起飞! 最近Homebrew更新至最新版,每次执行 brew 命令时都会自动从官方地址 https://formulae.…...
django blank 与 null的区别
1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是,要注意以下几点: Django的表单验证与null无关:null参数控制的是数据库层面字段是否可以为NULL,而blank参数控制的是Django表单验证时字…...
