Vue.js设计与实现阅读-2

news2024/11/16 12:05:31

Vue.js设计与实现阅读-2

    • 1、前言
    • 2、框架设计的核心要素
        • 2、1 提升用户体验
        • 2、2 控制代码体积
        • 2、3 Tree-Shaking
        • 2、4 特性开关
        • 2、5 错误处理

1、前言

上一篇我们了解到了

  • 命令式和声明式的区别,前者关注过程,后者关注结果
  • 了解了虚拟dom存在的意义,使找出差异这个过程消耗的性能最小化
  • 学习了进行时、编译时、编译时+进行时的特点,初步知道了vue3是采用编译时+进行时的框架

2、框架设计的核心要素

2、1 提升用户体验
好的用户开发体验,是衡量框架是否优秀的指标之一。

提供友好的警告信息

在这里插入图片描述
当我们创建一个Vue.js应用,并把他挂载在一个不存在的dom节点,就会发现控制台有 warning 信息。
在这里插入图片描述
从警告信息中,能够快速知道失败原因,我们提供的选择器没有找到对应的 DOM 元素。如果Vue 内部不做处理,可能得到的是 Uncaught TypeError: Cannot read property ‘xxx’ of null 就不能很快定位到问题。

那 Vue 中是如何实现的,可以看 Vue 源码中有 warn 函数的调用

看代码可以看到,在创建Vue应用的时候,app.mount中调用了一个 normalizeContainer 函数,对于传入的参数进行处理,确保是一个有效的 DOM 元素。
在这里插入图片描述
在 normalizeContainer 函数中,可以看到图中圈出的 if 判断,当 处于开发者模式并且 通过 document.querySelector 方法没有找到匹配的 DOM 元素时,会输出警告信息。
在这里插入图片描述

再往里面看 warn 函数,发现最终都是调用了 console.warn 函数,进行输出警告在这里插入图片描述

2、2 控制代码体积
框架的大小也是衡量框架的标准。同样情况下,使用的代码越少,体积就越小,浏览器加载资源的时间越少。
但是 Vue 中有大量的提示信息,越完善的提示信息就意味着越多的代码。
那 Vue3 中是如何处理的

看代码 会发现 每一个调用 warn 函数的地方 都会配合 __DEV __ 的常量检查
在这里插入图片描述
只有当 __DEV __ 为 true 的 前提下,才有可能会打印警告信息。这里的 DEV 常量就是达到目的的关键。

Vue.js 在输出资源的时候,会输出两个版本,开发环境和生产环境。当 Vue.js 构建用于开发环境的时候,会把 __DEV __ 设置为 true ,当处于生产环境的时候会设置为 false。那么那段警告代码就永远不会执行。
就能实现在开发环境为用户提供友好的警告信息,在生产环境中却不会增加代码体积。

2、3 Tree-Shaking

上面说到通过设置预定义常量 __DEV __ ,能够在生产环境中不包含用于打印警告信息的代码。但是这还不够,比如Vue内有很多组件,比如< transition > 组件,我们可能项目中都没用到这个组件,那他应该不需要包含在我们项目最终的构建资源中。Vue是如何实现的呢?

先揭晓答案吧,是通过 Tree-Shaking 实现的。 Tree-Shaking 用来消除那些永远不会被执行的代码(排除 dead code)。rollup.js和webpack 都支持 Tree-Shaking 。来看下 webpack 中, Tree-Shaking 如何工作。参考文档Tree-Shaking

创建一个 webpack 项目, 目录结构如下:
在这里插入图片描述
配置 webpack.config.js 如下

const path = require('path');

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist'),
  },
  mode: 'development',
  optimization: {
   usedExports: true,
 },
};

其中在 math 中导出了两个方法:

export function square(x) {
    return x * x;
}

export function cube(x) {
    return x * x * x;
}

index.js 中调用 了 cube 方法

import { cube } from './math.js';

function component() {
    const element = document.createElement('pre');
    element.innerHTML = [
        '你好 webpack!',
        '5 的立方等于 ' + cube(5)
      ].join('\n\n');

    return element;
}

document.body.appendChild(component());

注意这里我们并没有导出 square 函数,按理说,最终的编译打包产物中应该是没有 square 函数的相关内容的。我们继续往下查看结果

使用 npm run build 查看 bundle.js中打包编译后的结果。
在这里插入图片描述

/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */  cube: () => (/* binding */ cube)\n/* harmony export */ });\n/* unused harmony export square */\nfunction square(x) {\n    return x * x;\n  }\n  \n  function cube(x) {\n    return x * x * x;\n  }\n\n//# sourceURL=webpack://webpack-demo/./src/math.js?");

/***/ })

/******/ 	});

看上方的 unused harmony export square 注释。仔细观察下面的代码会发现尽管没有引用 square,但它仍然被包含在 bundle 中。
在纯 ES 模块中,很容易识别出哪些文件有副作用,但是我们的项目没有办法达到这种纯度,因此我们需要提示 webpack 编译器哪些代码是纯粹的。

我们可以通过 /#PURE/ 注释来帮助 webpack,告诉他某个函数调用无副作用,她会被标记为 dead code,不会被执行且会被清除掉。
我们尝试在 square 函数前面加上这样一个标记,然后再来看 bundle.js 中的输出,可以看到已经没有 square函数的引入了。

(()=>{"use strict";document.body.appendChild(function(){const n=document.createElement("pre");return n.innerHTML=["你好 webpack!","5 的立方等于 "+(5,125)].join("\n\n"),n}())})();

基于以上 我们可以看到,在编写框架的时候可以合理的使用 /#PURE/ 注释。查看 Vue3 的源码,可以发现大量的 /#PURE/ 使用。
在这里插入图片描述

2、4 特性开关

设计框架的时候,会给用户提供多种功能,例如提供 A、B、C三个特性给用户,同时提供了a、b、c三个对应的开关,用户可以通过设置 a、b、c 为true 或者 false,代表开启或者关闭特性。
对于设置关闭的特性,可以利用 Tree-Shaking 机制让其不包含在最终资源中,带来了极大灵活性。

如何实现特性开关。其实类似于上面的 DEV 常量一样,本质上是利用 rollup.js 来预定义常量插件来实现。
比如 VUE_OPTIONS_API

      __FEATURE_OPTIONS_API__: isBundlerESMBuild
        ? `__VUE_OPTIONS_API__`
        : `true`,

其中 VUE_OPTIONS_API 是一个特性开关,用户可以通过设置 VUE_OPTIONS_API 预定义常量的值来控制是否要包含这段代码,这个标志是用来对 Vue2 做适配.
比如 Vue2中的 template、data 等选项其实都属于 Options API,但在 Vue3 中,这种 Options API 写得相对来说就比较少了,
现在一般在 Vue3 中编写 Composition API,默认情况下,这个 VUE_OPTIONS_API 标志默认值是 true,这就意味着默认情况下 Vue3 项目中会包含支持 Options API 的这部分代码。
那么,如果在项目中编写的都是 Composition API 代码,其实就不再需要这部分解析 Options API 的代码了,那么可以通过 设置 VUE_OPTIONS_API 为true,来剔除掉一些无用大代码,减少代码体积。

2、5 错误处理

错误处理是框架开发的重要环节。
假设我们提供了一个方法,

export default {
	foo(fn) {
		fn && fn()
	}
}

用户侧使用

import utils from 'utils.js'
utils.foo(() => {
	...
})

如果函数执行出错,有两个方法,1用户自己执行 try…catch处理

import utils from 'utils.js'
utils.foo(() => {
	try {
		//...
	} catch(e) {
		//...
	}
})

这样的话,用户每使用一个函数,都需要加一个错误处理程序。很烦。
第二个就是我们内部统一处理,封装一个错误处理函数, callWithErrorHandling。

export default {
	foo(fn) {
		callWithErrorHandling(fn)
	},
	bar(fn) {
		callWithErrorHandling(fn)
	}
}
function callWithErrorHandling(fn) {
	try {
		fn && fn()
	} catch(e) {
		console.log(e)
	}
}

这样代码看起来简洁,再升级下可以为用户提供统一的错误处理接口。

let handleError = null
export default {
	foo(fn) {
		callWithErrorHandling(fn)
	},
	// 暴露给用户,用户可以调用该函数注册统一的处理函数
	registerErrorHandler(fn) {
		handleError = fn
	}
}
function callWithErrorHandling(fn) {
	try {
		fn && fn()
	} catch(e) {
	// 将错误传递给用户的错误处理程序
		handleError(e)
	}
}

用户侧

import utils from 'utils.js'  // 注册错误处理程序
utils.registerErrorHandler((e) => {
	// 做统一的处理,可以选择忽略,可以上报。
   console.log(e)
 })
 utils.foo(() => {/*...*/})
 utils.bar(() => {/*...*/})

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

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

相关文章

Excel地址

解题思路&#xff1a; 根据题中歪歪和笨笨的话可以有两种解法。 1.输入的数为多大&#xff0c;则循环1多少次&#xff0c;当值为27时就要进行进位操作。这时要分情况讨论。 当集合中元素为一个时&#xff0c;如26&#xff0c;则需要变为1 1&#xff0c;集合元素个数加一。 当…

C语言指针(一)

目录 1.什么是指针 2.指针变量和地址 1.解引用操作符 2.指针变量类型的意义 3.void*指针 4.const修饰指针 1.const放在*左边 2.const放在*右边 3.指针的运算 1.指针加减整数 2.指针减指针 3.指针比较大小 4.野指针 1.没有给指针变量初始化 2.指针指向的空间释放 …

MES系统中的设备管理及设备数据采集

随时工厂数字化建设的大力推进&#xff0c;设备管理的效率得到了很大的提升&#xff0c;特别是作为机加工企业&#xff0c;设备是整个企业非常重要的核心资产。 一、设备进行数据采集面临痛点&#xff1a; 设备数据状况无法获取与掌握 设备老旧&#xff0c;信息化基础差&…

制造知识普及--MES系统中的调度排产管理

要想弄清楚MES系统调度排产的管理机制&#xff0c;则要首先搞清楚车间调度排产是一套怎样的工作流程&#xff0c;它的难点在什么地方&#xff1f; 生产调度指的是具体组织实现生产作业计划的工作&#xff0c;是对执行生产作业计划过程中发生的问题和可能出现的问题&#xff0c…

Springboot+vue学生考试系统

Springbootvue学生考试系统 演示视频 【Springbootvue学生考试系统】 https://www.bilibili.com/video/BV1gk4y1Q7em/?share_sourcecopy_web&vd_source11344bb73ef9b33550b8202d07ae139b 主要功能&#xff1a; 管理员可以添加题库分配课程教师&#xff0c;指定考试范围指定…

性能测试分析案例-定位服务吞吐量下降

环境准备 预先安装 docker、curl、wrk、perf、FlameGraph 等工具 sudo yum groupinstall Development Tools # 安装火焰图工具 git clone https://github.com/brendangregg/FlameGraph # 安装wrk git clone https://github.com/wg/wrk cd wrk && make && sud…

LeetCode 38 外观数列

题目描述 外观数列 给定一个正整数 n &#xff0c;输出外观数列的第 n 项。 「外观数列」是一个整数序列&#xff0c;从数字 1 开始&#xff0c;序列中的每一项都是对前一项的描述。 你可以将其视作是由递归公式定义的数字字符串序列&#xff1a; countAndSay(1) "1…

数字信号处理 唐向宏著 pdf +课后答案 免费下载

数字信号处理——原理、实现与仿真 pdf 唐向宏著 &#xff0b;课后答案 杭州电子科技大学 费劲心思在网上花钱买的&#xff0c;共享给大家 永久链接&#xff1a;https://wwi.lanzoup.com/b0140pf4f 密码&#xff1a;aflj 里面除了有原书PDF&#xff0c;还有课后题答案

二极管选型怎么选?常用参数要熟练~

同学们大家好&#xff0c;今天我们继续学习杨欣的《电子设计从零开始》&#xff0c;这本书从基本原理出发&#xff0c;知识点遍及无线电通讯、仪器设计、三极管电路、集成电路、传感器、数字电路基础、单片机及应用实例&#xff0c;可以说是全面系统地介绍了电子设计所需的知识…

AnyText多语言文字生成与编辑模型——让AI绘图自由添加精美文字

随着AIGC的爆火,图片生成技术得到飞速发展,当前AI生成的图片已达到真假难辨的高保真度。例如stable diffusion与midjourney为代表的文生图大模型。不过,当合成图片中出现文字内容时,现存的AI技术依然无法驾驭文字内容。因此,modescope提出了一种新型的文字生成方法,此方法…

数谷·企声|贵州空港智能科技:以“智”提“质”,助力贵阳智慧机场建设

当前&#xff0c;我国民航正大力推进“平安、绿色、智慧、人文”的四型机场建设。贵州空港智能科技有限公司&#xff08;下称“空港智能科技”&#xff09;作为贵州民航产业集团有限公司&#xff08;下称“民航产业集团”&#xff09;信息化建设的排头兵和主力军&#xff0c;近…

SQL-条件查询与聚合函数的使用

&#x1f389;欢迎您来到我的MySQL基础复习专栏 ☆* o(≧▽≦)o *☆哈喽~我是小小恶斯法克&#x1f379; ✨博客主页&#xff1a;小小恶斯法克的博客 &#x1f388;该系列文章专栏&#xff1a;重拾MySQL &#x1f379;文章作者技术和水平很有限&#xff0c;如果文中出现错误&am…

(leetcode)Z字形变换 -- 模拟算法

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 题目链接 . - 力扣&#xff08;LeetCode&#xff09; 输入描述 string convert(string s, int numRows)&#xff0c;输入一个字符串s&#xff0c;以及一个行数numRows&#xff0c;将字符串按照这个行数进行Z字形排列&…

FPGA UDP协议栈:基于88E1111,支持RGMII、GMII、SGMII三种模式,提供3套工程源码和技术支持

目录 1、前言免责声明 2、相关方案推荐我这里已有的以太网方案本协议栈的 1G-UDP版本本协议栈的 10G-UDP版本本协议栈的 25G-UDP版本1G 千兆网 TCP-->服务器 方案1G 千兆网 TCP-->客户端 方案10G 万兆网 TCP-->服务器客户端 方案 3、该UDP协议栈性能4、详细设计方案设…

C练习——魔术师猜三位数

题目&#xff1a; 有一种室内互动游戏&#xff0c;魔术师要每位观众心里想一个三位数abc&#xff08;a、b、c分别是百位、十位和个位数字&#xff09;&#xff0c;然后魔术师让观众心中记下acb、bac、bca、cab、cba五个数以及这5个数的和值。只要观众说出这个和是多少&#xf…

使用Python进行客户行为分析

客户行为分析是一个有价值的过程&#xff0c;它使企业能够做出数据驱动的决策&#xff0c;增强客户体验&#xff0c;并在动态市场中保持竞争力。 下面是我们可以遵循的客户行为分析任务的过程&#xff1a; 收集与客户互动相关的数据。它可以包括购买历史记录&#xff0c;网站…

C桑(Cython)从入门到入土(2): np数组操作对比

C桑(Cython)从入门到入土 2. np数组操作对比 Node sc518 Copy has image data of type unsigned long long实际上, &#x1f446;&#x1f3fb;这个错误是我探索Cython的缘起… code1: Form: 更现代的方法是使用内存视图而不是指针&#xff1a; cdef np.uint32_t[:,:,::1] …

爬虫逆向破解翻译接口参数

Python 请求baidu翻译接口&#xff1a;https://fanyi.baidu.com/v2transapi?fromzh&toen 步骤一&#xff1a; 查找构建请求参数 JS 断点发现如下参数&#xff1a; w {from: _.fromLang,to: _.toLang,query: e,transtype: i,simple_means_flag: 3,sign: b(e),token: windo…

【Linux】宝塔端口不通

1.问题描述&#xff1a;端口不通 以端口16588为例&#xff1a; 服务器16588端口是关闭的&#xff0c;防火墙规则是放通的&#xff0c;是由于服务器内的对应程序没有监听到 对应 的公网上 图1&#xff1a;端口检测 图2&#xff1a; 端口已放行 此时访问仍然不通&#xff0c;但…

Error: start of central directory not found; zipfile corrupt.

【报错】使用 unzip 指令在 AutoDL 上解压 .zip 文件时遇到 Error: start of central directory not found; zipfile corrupt. 报错&#xff1a; 重新上传后还是解压失败排除了 .zip 文件上传中断的问题。 【原因】Windows 和 Linux 下的压缩文件的二进制格式有所不同&#x…