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

这篇具有很好参考价值的文章主要介绍了Vue.js设计与实现阅读-2。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1、前言

上一篇我们了解到了

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

2、框架设计的核心要素

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

提供友好的警告信息

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

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

看代码可以看到,在创建Vue应用的时候,app.mount中调用了一个 normalizeContainer 函数,对于传入的参数进行处理,确保是一个有效的 DOM 元素。
Vue.js设计与实现阅读-2,vue.js,前端,Vue设计与实现
在 normalizeContainer 函数中,可以看到图中圈出的 if 判断,当 处于开发者模式并且 通过 document.querySelector 方法没有找到匹配的 DOM 元素时,会输出警告信息。
Vue.js设计与实现阅读-2,vue.js,前端,Vue设计与实现

再往里面看 warn 函数,发现最终都是调用了 console.warn 函数,进行输出警告Vue.js设计与实现阅读-2,vue.js,前端,Vue设计与实现

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

看代码 会发现 每一个调用 warn 函数的地方 都会配合 __DEV __ 的常量检查
Vue.js设计与实现阅读-2,vue.js,前端,Vue设计与实现
只有当 __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 项目, 目录结构如下:
Vue.js设计与实现阅读-2,vue.js,前端,Vue设计与实现
配置 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中打包编译后的结果。
Vue.js设计与实现阅读-2,vue.js,前端,Vue设计与实现

/***/ ((__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/ 使用。
Vue.js设计与实现阅读-2,vue.js,前端,Vue设计与实现

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)
	}
}

用户侧文章来源地址https://www.toymoban.com/news/detail-783680.html

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

到了这里,关于Vue.js设计与实现阅读-2的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 毕业设计So Easy:SpringBoot+Vue图书阅读和管理系统(前端+后端+小程序端)

    目录 1、项目概述 2、开发环境 3、前后端配置部署 4、小程序端配置部署 5、项目效果演示 5.1、后端管理平台 5.2、前端阅读平台 5.3、小程序社区平台 很多计算机专业大学生经常和我交流:毕业设计没思路、不会做、论文不会写、太难了...... 针对这些问题,决定分享一些软、

    2024年02月11日
    浏览(46)
  • 基于vue的小说阅读网/基于springboot的小说网站/阅读网站的设计与实现

    随着信息技术和网络技术的飞速发展,人类已进入全新信息化时代,传统管理技术已无法高效,便捷地管理信息。为了迎合时代需求,优化管理效率,各种各样的管理系统应运而生,各行各业相继进入信息管理时代, 小说阅读网 就是信息时代变革中的产物之一。 任何系统都

    2024年02月11日
    浏览(39)
  • vue前端开发中,通过vue.config.js配置和nginx配置,实现多个入口文件的实现方法

    由于vue为单页面项目,通过控制组件局部渲染,main.js是整个项目唯一的入口,整个项目都在一个index.html外壳中。 若项目过大,会造成单页面负载过重;同时,多页面利于模块独立部署。 如果项目中不同的页面需要不同的main.js和App.vue这样就需要配置多个入口了。 要单独将页

    2024年01月22日
    浏览(87)
  • 前端js react vue怎么实现在线预览doc文档

    先说结论: 目前在纯前端层面没有很好的方案,基本都需要服务端的介入。 优点 :简单易用,无需配置 缺点 :文档需要支持外网访问,且文档会是公开可见的,所以对于一些内部敏感的文档来说,这个显然是不可行的。 需要后端介入配合 onlyoffice地址 这个也要先在服务器

    2024年02月15日
    浏览(81)
  • Vue.js设计与实现

    1.1 命令式和声明式 从范式上看,视图层框架分为命令式和声明式。 命令式: 一大特点是: 关注过程 声明式: 一大特点是: 关注结果 1.2 性能与可维护性 声明式代码的性能不优于命令式代码的性能 框架本身就是封装了命令式代码才实现了面向用户的声明式 声明式 代码的

    2024年02月08日
    浏览(30)
  • 基于Java+Vue+uniapp微信小程序小说阅读系统设计和实现

    博主介绍 : ✌ 全网粉丝30W+,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行交流合作 ✌ 主要内容: SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、P

    2024年01月19日
    浏览(59)
  • vue+face-api.js实现前端人脸识别功能

    近期做了一个前端vue实现人脸识别的功能,主要功能逻辑包含:人脸识别,人脸验证,唤起摄像头视频流之后从三个事件(用户点头、摇头、眨眼睛)中随机选中两个事件,待两个事件通过判断后人脸静止不动3秒钟后截取视频流生成图片,上传到阿里或者腾讯oss,通过oss返回

    2024年02月05日
    浏览(42)
  • 《Vue.js 设计与实现》—— 02 框架设计核心要素

    框架设计并非仅仅实现功能那么简单,里面有很多学问。例如: 框架应该给用户提供哪些构建产物?产物的模块格式如何? 当用户没有以预期的方式使用框架时,是否应该打印合适的警告信息从而提供更好的开发体验,让用户快速定位问题? 开发版本和生产版本的构建有何

    2024年02月03日
    浏览(46)
  • Vue前端 更具router.js 中的meta的roles实现路由卫士,实现权限判断。

    参考了之篇文章 1、我在登陆时获取到登录用户的角色名roles,并存入sessionStorage中,具体是在login页面实现,还是在menu页面实现都可以。在menu页面实现,可以显得登陆快一些。 2、编写router.js,注意,一个用户可能有多个角色。 这里有个bug 我们的roles存在sessionStorage中,关闭

    2024年02月13日
    浏览(45)
  • 基于Java+Vue+uniapp微信小程序微信阅读网站平台设计和实现

    博主介绍 : ✌ 全网粉丝30W+,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战 ✌ 🍅 文末获取源码联系 🍅 👇🏻 精彩专栏 推荐订阅 👇🏻 不然下次找不到哟 2022-2024年

    2024年02月06日
    浏览(58)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包