对vite的理解
下一代构建打包工具。
那么如何理解下一代呢?
随着项目越来越大,需要处理的JavaScript呈指数级增长,模块越来越多。构建工具需要很长的时间才能开启服务器,HMR也需要几秒钟才能在浏览器反应出来。所以vite的构建速度非常快。
- 一个开发服务器,它基于原生ES模块提供了丰富的内建功能,HMR的速度非常快速。
- 一套构建指令,它使用rollup打开我们的代码,并且它是预配置的,可以输出生成环境的优化过的静态资源。
vite是默认支持css, ts的,以及css预处理语言的。只需要安装对应的包,而无需配置像webpack中的loader。
vite默认不支持vue,需要安装对应的插件。@vitejs/plugin-vue, @vue/compiler-sfc
。并在vite.config.js
文件进行配置。
vite实现原理
那么为什么vite会支持ts和css预处理语言呢?
- vite会创建一个本地服务器,类似于webpack通过express, 他是通过connect来实现的。主要是为了请求转发。
- vite内部将ts, less, sass等文件转化为es module 的js语法。并且依旧以原来的文件命名。然后通过connect将转化的文件返回给浏览器。
进制转换
- parseInt(num, 基底)。指定num为几进制数,然后转换为10进制。
- num.toString(基底)。将10进制的num转化为几进制的数。
判断数据类型的方法
object的tostring和构造器的tostring的区别
Number、String,Boolean,Array,RegExp、Date、Function等内置对象均重写了Object原型上的toString方法,作用是将当前数据类型转为字符串类型。
const num = 123; num.toString(); // 该toString调用的是Number.prototype.toString方法。 // 但是Number.prototype.__proto__ = Object.prototype // Object中也存在tostring函数。该函数返回的是当前对象的类型字符串。[object Number] // 所以各个包装类和内置类都重写了toSring方法。
原型链的了解
每一个对象的__proto__
属性都指向他的原型对象prototype。直到Object.prototype。并且对象中获取属性和方法都是通过这个指向来查找的。并且es5之前有些继承也是通过原型链。
说三种事件绑定的方式
developer.mozilla.org/zh-CN/docs/…
- 行内事件处理器(不建议使用)
- 事件处理器属性 (他还只能对同一元素同一事件添加一个,后添加的会覆盖前面的 )
- addEventListener, removeEventListener。(支持到ie9, 可以对同一元素添加多个相同事件类型的事件不会相互覆盖。)
flex布局的意义
依靠它可以实现一些响应式操作,比如我们要一个容器固定在中间,即使我们的窗口大小发生变化。 同时也解决了元素的排列问题,让元素按行,按列排列。
元素隐藏的方式
- opacity: 0。元素不可见,但是还会占据空间,而且,需要注意,此时给它绑定事件,它会触发。
- display: none。直接把元素隐藏了,不占据任何空间,也不响应任何事件。
- visibility:hidden。
visibility
值为hidden
,元素不可见,但是还会占据空间,虽然它占据空间,但是如果给它绑定事件,它也不会触发。
- transfrom: scale(0)。不可见,还会占据空间,但是绑定的事件不会触发。跟
visibility:hidden
表现一致。
- width: 0, height: 0。如果它有子元素,还得设置overflow设置为
hidden
。
- overflow: hidden。隐藏溢出部分。
- position定位偏移。
- 绝对定位+z-index。让元素之间覆盖。
this指向问题
- 默认绑定
- 隐式绑定
- 显示绑定
- new 绑定
Vue2和Vue3的区别
- vue3新增suspense(实验中),teleport组件。
- vue2使用options API, vue3使用composition API 实现逻辑模块化的复用。
- vue2使用flow做类型检测,vue3全部使用ts重构。
- vue2通过Object.definePrototype做数据响应式。vue3通过Proxy做数据响应式。
- vue3对比vue2具有明显的性能提升
- 打包大小减少41%
- 初次渲染快55%,更新快133%
- 内存使用减少54%
- 生命周期的变化。有更好的语义化。
- beforeCreate -> 请使用 setup()
- created -> 请使用 setup()
- beforeMount -> onBeforeMount
- mounted -> onMounted
- beforeUpdate -> onBeforeUpdate
- updated -> onUpdated
- beforeDestroy -> onBeforeUnmount
- destroyed -> onUnmounted
- errorCaptured -> onErrorCaptured
- vue2只能有一个根节点,但是vue3可以有多个根节点,并且需要手动指定非props的属性绑定在那个dom上。
- 单文件组件组合式 API 语法糖。
script setup
defineExpose
,setup模板默认情况下是关闭的,那么通过ref, $parent获取组件实例,他是不会获取到setup模板中的属性的。所以我们可以通过defineExpose导出需要获取的东西。
- 与script一起使用
<script setup>
可以和普通的 <script>
一起使用。普通的 <script>
在有这些需要的情况下或许会被使用到: 无法在 <script setup>
声明的选项,例如 inheritAttrs 或通过插件启用的自定义的选项。声明命名导出。运行副作用或者创建只需要执行一次的对象。
- 状态驱动的动态 CSS。v-bind函数支持传入一个js表达式,但是需要使用引号包裹起来。
实际的值会被编译成 hash 的 CSS 自定义 property,CSS 本身仍然是静态的。自定义 property 会通过内联样式的方式应用到组件的根元素上,并且在源值变更的时候响应式更新。
<template> <div class="text">hello</div> </template> <script> export default { data() { return { color: 'red' } } } </script> <style> .text { color: v-bind(color); } </style>
- 配置全局属性的变化。vue2是创建多个根Vue实例来绑定全局配置。但是vue3是通过createApp来创建一个根Vue实例绑定全局配置。
- v-model在自定义组件上的修改。
- v-if 和 v-for两者作用于同一个元素上时,
v-if
会拥有比v-for
更高的优先级。
v-bind="object"
和一个相同的独立 attribute之间的覆盖规则。vue2总是独立的attribute覆盖object中同名的attribute。但是vue3中是后写的覆盖先写的。和object添加属性的行为一样。
- 非emits配置的事件,自动添加到根dom上。废除v-on.native。v-on.native作用是将原生 DOM 监听器添加到子组件的根元素中。
proxy和defineProperty的优缺点
vue2对于新增的属性无能为力,比如无法监听属性的添加和删除、数组索引和长度的变更,vue2的解决方法是使用Vue.set(object, propertyName, value) 等方法向嵌套对象添加响应式。
defineProperty
- 新添加的属性不是响应式。通过
$set
解决。
- 需要深度遍历对象依次添加响应式,性能消耗大。解决方案
Proxy
。
- 通过数组下标修改无法更新视图。因为过于消耗性能。
proxy的优点
- proxy劫持的是整个对象,对新增加的属性依旧是可以监听的。
- proxy可以劫持对对象的13种操作。
设置style标签的scoped属性
他会出现穿透。所以我们一般都不要直接使用标签设置样式。都通过class属性设置。并且给每个组件的根标签设置一个class。
extends, mixins
mixins
复用代码逻辑。并且vue3中的data是浅层合并。即只要原组件中data中存在的属性,mixin都不会合并。
如果修改mixins中的数据,他只会影响当前组件,不会影响其他组件中引入的mixins数据。只要记住,通过mixins引入后,他就表示的是自己组件的一部分了和别的无关系了。
- 如果是data函数的返回值对象
- 返回值对象默认情况下会进行合并;
- 如果data返回值对象的属性发生了冲突,那么会保留组件自身的数据;
- 如何生命周期钩子函数
- 生命周期的钩子函数会被合并到数组中,都会被调用。并且混入的生命周期先执行。
- 值为对象的选项
- 比如都有methods选项,并且都定义了方法,那么它们都会生效。将被合并为同一个对象。
- 但是如果对象的key相同,那么会取组件对象的键值对。
extends
允许一个组件扩展到另一个组件,且继承该组件选项。不能继承template内容。 几乎和mixins相同。合并策略和mixins一样。
mixins
选项主要用来组合功能,而 extends
主要用来考虑继承性。
cdn是什么?
CDN,全称是“Content Delivery Network”,翻译过来就是内容分发网络。它应用了 HTTP 协议里的缓存和代理技术,代替源站响应客户端的请求。它可以缓存源站的数据。
它就是专门为解决“长距离”上网络访问速度慢而诞生的一种网络应用服务。
CDN 的最核心原则是就近访问,如果用户能够在本地几十公里的距离之内获取到数据,那么时延就基本上变成 0 了。
cdn将原站上的数据缓存到每个网络节点上。用户在上网的时候就不直接访问源站,而是访问离他“最近的”一个 CDN 节点,术语叫“边缘节点”(edge node),其实就是缓存了源站内容的代理服务器,这样一来就省去了“长途跋涉”的时间成本,实现了“网络加速”。
CDN 的负载均衡
我们再来看看 CDN 是具体怎么运行的,它有两个关键组成部分:全局负载均衡和缓存系统。
全局负载均衡(Global Sever Load Balance)一般简称为 GSLB,它是 CDN 的“大脑”,主要的职责是当用户接入网络的时候在 CDN 专网中挑选出一个“最佳”节点提供服务,解决的是用户如何找到“最近的”边缘节点,对整个 CDN 网络进行“负载均衡”。
缓存系统是 CDN 的另一个关键组成部分,相当于 CDN 的“心脏”。如果缓存系统的服务能力不够,不能很好地满足用户的需求,那 GSLB 调度算法再优秀也没有用。缓存系统只能有选择地缓存那些最常用的那些资源。如果将这些 DOM 变化做成异步的消息事件, 添加到消息队列的尾部,那么又会影响到监控的实时性,因为在添加到消息队列的过程中,可能前面就有很多任务在排队了。
这也就是说,如果 DOM 发生变化,采用同步通知的方式,会影响当前任务的执行效率;
如果采用异步方式,又会影响到监控的实时性。那该如何权衡效率和实时性呢?
这就需要使用到微任务了。
为什么需要this
因为 JavaScript 语言的作用域链是由词法作用域决定的,而词法作用域是由代码结构来确定的。
如果想要访问上层作用域中的变量,那么我们就可以使用this。