Vue3源码解析,打造自己的Vue3框架-百度网盘|完结无密

2023-05-25 0 1,069

Vue3源代码导出,打造出她们的Vue3架构

——————

浏览の地止:https://www.lexueit.com/4748.html

——————

Vue3源码解析,打造自己的Vue3框架-百度网盘|完结无密Vue3源码导出,打造出她们的Vue3架构

Vue3源代码阐释(一)- 架构结构设计

架构结构设计里四处都充分体现了取舍的表演艺术。

当他们写作Vue3源代码时辨认出,整座架构会依照组件间展开分割,但组件间又并非互相分立的,而要互相关联,有提及亲密关系,做为两个架构结构斯特默,具体来说要做的是对架构总体展开结构设计,对各组件机能展开明晰的分割

陈述句与新闻稿式

具体来说快照层架构一般来说气氛陈述句与新闻稿式,她们各有优劣

陈述句架构特征是,比如JQuery是众所周知的陈述句架构

$(#app).text(hello world).on(click, () => { alert(hi)})// 设置文本内容hello world// 绑定点击事件

可以看出代码本身描述的事是做事的过程,这符合他们的逻辑直觉

新闻稿式架构的特征是,比如Vue.js

<div @click=“() => alert(hi)”>hello world<

/div>

这段类html模板语法是vue实现与jq写法一样机能,只需看到结果,至于如何实现由vue.js帮他们处理

新闻稿式代码比陈述句代码多出了找出差异的性能消耗,Vue架构本身是封装了陈述句代码才实现了面向用户的新闻稿式,所以新闻稿式代码性能不会优于陈述句代码的性能,那么为什么Vue.js还会选择新闻稿式结构设计呢?原因在于新闻稿式代码可维护性更强,如果采用陈述句开发,需要开发者维护整座过程,包括手动完成DOM元素创建、更新、删除等工作,而新闻稿式展示的是开发者要的结果,看上去更加直观,至于过程,vuejs都为他们封装好了

这就充分体现了架构结构设计在可维护性与性能间的取舍,而架构结构设计核心是:在保持可维护性的同时让性能损失最小化

虚拟DOM的性能

新闻稿式代码更新性能 = 找出差异的性能消耗 + 直接修改的性能消耗

如果他们能够最小化找出差异的性能消耗,就能让新闻稿式代码无限接近陈述句代码性能。而所谓的虚拟DOM,是为了最小化找出差异这这一步性能消耗而出现的

运行时和编译时

架构结构设计有三种选择:纯运行时、运行时+编译时、纯编译

运行时 使用render函数将对象渲染成DOM元素const obj = {tag: div,children: [ {tag: span,children: hello world } ]}Render(obj, document.body)// 实现render函数functionRender(obj, root) {const el = document.createElement(obj.tag)if (typeof obj.children === string) {const text = document.createTextNode(obj.children) }elseif (obj.children) { obj.children.forEach((child) =>Render(child, el)) }}编译时<div><span>hello world</span><

/div>

/

/ 编译

const obj = {

tag: div,

children: [

{

tag: span,

children: hello world

}

]

}

运行+编译时// 封装两个compiler函数,html结构转为对象const obj = compiler(html)// 再调用展开渲染Render(obj, document.body)

控制架构代码的体积

架构的大小是衡量两个架构标准之一,在实现同样机能情况下,用到的代码越少越好,这样体积越小,浏览器加载资源时间就会越少 在vue3源代码中每两个warn函数调用都会配合__dev__常量的检查,比如:

if (__dev__ && !res) { warn(`failed to mount app: mount target selector “${container}” returned null` )}

Vue.js在使用rollup.js对项目展开构建,这里的__dev__常量实际上是通过rollup.js插件配置来预定义的,其机能与webpack中DefinePlugin类似。

在打包制品时,__dev__常量会被替换成false,这段代码永远不会执行,在构建资源时候会被移除,最终也不会出现在产物中,这样就做到了在开发环境为用户提供友好的警告信息同事,不会增加生产环境代码体积

架构要做到良好的Tree-Shaking

上文中提到自定义常量__DEV__,能够在生产环境不包含用于打印警告的代码,但这还远远不够,Vue.js内建了很多组件,比如组件,如果他们没有用到该组件,那么他的代码是不需要包含在生产环境资源里的,那么如何做到的呢?这就不得不提到Tree-Shaking

什么是Tree-Shaking

这个概念因rollup.js而普及。简单的说,Tree-Shaking是消除永远不用的代码,也是排除dead code,现在不论是rollup还是webpack都支持Tree-Shaking

想要实现Tree-Shaking必须满足两个条件,组件必须是ESM(ES Module),因为Tree-Shaking是依赖ESM的的静态结构,

// input.jsimport { foo } from./utils.js foo()// utils.jsexportfunctionfoo(obj) { obj && obj.foo }exportfunctionbar(obj) { obj && obj.bar }

执行如下命令展开构建:

npx rollup input.js -f esm -o bund.js

输出内容如下:

// bund.jsfunctionfoo(obj) { obj && obj.foo }

输出产物没有包含bar函数,Tree-Shaking起了作用,因为没有用到bar函数,因此可以做为dead code被删除了,

但foo函数执行也没有什么意义,仅仅是读取了对象的值,所以执行了也没有什么必要,为什么rollup没有做为dead code移除呢?这就涉及到两个关键点-副作用

什么是副作用

当调用函数的时候对外部产生影响,比如修改了全局变量,但他们的方法仅仅是读取了对象的值,怎么会产生副作用,其实是可能的,如果obj对象是通过Proxy创建的代理对象,当他们读取对象属性时,就会触发代理对象get,在get夹子中是有可能产生副作用的。因此静态分析js代码很有难度,所以像rollup 提供两个机制,让他们很明确告诉rollup,“放心吧,这段代码不出出现副作用,可以移除”,可以修改input.js为:

import { foo } from./utils/*#__PURE__*/ foo()

注意注释代码/#PURE/,其作用是告诉rollup,对于foo函数调用不会产生副作用,可以放心展开Tree-Shaking

在vue3源代码中,大量使用了该注释,比如:

exportconst isHTMLTag = /*#__PURE__*/makeMap(HTML_TAGS)

错误处理

错误处理是架构开发过程中重要环节,架构错误处理机制好坏决定了用户应用程序的健壮性,还决定了用户开发处理错误的心智负担。

// utils.jsexportdefault {foo(fn) { fn && fn() } }

该组件导出两个对象,其中foo属性是两个函数,接受两个回调函数做为参数,如果用户执行的时候出错了怎么办呢?第一种办法是用户自行处理,需要用户她们执行try…catch,这种会增加用户负担,假设导出有100方法,那就要写100次兼容性处理

第二种他们代替用户统一处理

// utils.jslet handlerError = nullexportdefault {foo(fn) { callWithErrorHandling(fn) }, registerErrorHandler(fn) { handlerError = fn } }functioncallWithErrorHandling(fn) {try { fn && fn() } catch(e) { handlerError(e) } }

用户可以使用registerErrorHandler函数注册错误处理程序,然后再callWithErrorHandling函数内部捕获错误后,把错误传递给用户注册的错误处理程序

Vue3源码解析,打造自己的Vue3框架-百度网盘|完结无密

举报/反馈

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务