vue3响应式原理
Vue 3 基于 ES6 的 Proxy 对象来实现响应式,而不再使用 Object.defineProperty。
在 Vue 3 中,当一个响应式对象被创建时,Vue 会使用 Proxy 对象包装它。Proxy 对象可以拦截对象上的各种操作,例如读取、写入和删除属性等。当我们对响应式对象进行操作时,Proxy 对象会拦截这些操作,并通知 Vue 去更新相关的视图。
vue2和vue3的区别
响应式系统(Reactivity System):Vue 3 引入了 Composition API,这是一种新的响应式系统。Composition API 提供了更灵活和强大的组件状态和逻辑管理方式,使代码组织和重用更加方便。Composition API 使用函数而不是对象,可以提高摇树优化(Tree Shaking)并减小打包体积。
更小的包体积:Vue 3 通过更好的 Tree Shaking 和更高效的运行时代码生成,相较于 Vue 2,打包体积更小。Vue 3 的响应式系统也经过优化,性能更好。
性能改进:Vue 3 采用了更快、更高效的渲染机制,得益于新的编译器。虚拟 DOM 的差异化算法经过优化,减少不必要的更新,提升渲染性能。
作用域插槽替代为
<slot>
:在 Vue 3 中,作用域插槽的概念被更直观、更简化的<slot>
语法所取代,使得在组件组合中定义和使用插槽更加容易。引入 Teleport 组件:Vue 3 引入了 Teleport 组件,可以在 DOM 树中的不同位置渲染内容,用于创建模态框、工具提示和其他覆盖层效果。
片段(Fragments):Vue 3 引入了一个名为片段(Fragment)的内置组件,允许将多个元素进行分组,而无需添加额外的包装元素。
更好的 TypeScript 支持:Vue 3 默认提供了更好的 TypeScript 支持,具有增强的类型推断和与 TypeScript 工具更好的集成。
简化的 API:Vue 3 对许多 API 进行了简化和优化,使得学习和使用框架更加容易。新的 API 提供了更好的一致性,并与 JavaScript 标准更加对齐。
对MVVM的理解
MVVM(Model-View-ViewModel)是一种软件架构模式,用于将应用程序的用户界面(View)与业务逻辑(Model)分离,并通过一个中间层(ViewModel)进行交互和数据绑定。
以下是对MVVM的基本理解:
Model(模型):代表应用程序的数据和业务逻辑。它可以是从后端获取的数据、本地存储的数据或者其他数据源。Model 不关心用户界面的展示,它只负责数据的获取、处理和存储。
View(视图):代表应用程序的用户界面。它负责展示数据给用户,并接收用户的输入。View 是 passively(被动地)接收来自 ViewModel 的数据,并将用户的操作传递给 ViewModel。
ViewModel(视图模型):是 View 和 Model 之间的中间层,负责处理 View 和 Model 之间的交互和数据绑定。ViewModel 从 Model 中获取数据,并将数据转换为 View 可以展示的格式。它还负责监听 View 的用户操作,并将这些操作转发给 Model 进行处理。ViewModel 通常实现了一些额外的逻辑,例如数据验证、计算属性等。
MVVM 的核心思想是数据绑定。ViewModel 通过数据绑定将 Model 中的数据与 View 中的元素进行关联,当 Model 的数据发生变化时,View 会自动更新,反之亦然。这种双向的数据绑定使得开发者不需要手动去更新视图,大大简化了开发过程。
MVVM 的优点包括:
分离关注点:将界面逻辑和业务逻辑分离,使代码更加可维护和可测试。
数据驱动:通过数据绑定实现自动更新视图,减少手动操作。
可重用性:ViewModel 可以被多个 View 共享,提高代码的重用性。
开发效率:MVVM 提供了一种结构化的开发模式,使开发者能够更快地开发应用程序。
需要注意的是,MVVM 是一种架构模式,并不依赖于具体的编程语言或框架。在实际开发中,可以使用不同的技术栈来实现 MVVM,例如使用 Vue.js、Angular、React 等前端框架。
虚拟dom
虚拟DOM(Virtual DOM)是一种用于提高Web应用性能的技术概念。它是在内存中构建的轻量级的DOM副本,用于描述真实DOM的结构和属性。通过对比虚拟DOM与真实DOM的差异,可以最小化对真实DOM的操作,从而提高性能。
虚拟DOM的工作原理如下:
初始渲染:当应用程序首次加载时,虚拟DOM会根据组件的描述信息构建一个虚拟DOM树。这个虚拟DOM树是一个轻量级的JavaScript对象,它包含了组件的结构和属性。
更新操作:当组件的状态发生变化时,虚拟DOM会重新构建一个新的虚拟DOM树。然后,它会将新旧虚拟DOM树进行比较,找出两者之间的差异。
差异计算:虚拟DOM会通过一系列算法,比较新旧虚拟DOM树之间的差异。这些差异可能包括节点的添加、删除、移动或属性的变化。
批量更新:虚拟DOM会将所有的差异记录下来,并批量更新到真实DOM上。这样可以减少对真实DOM的操作次数,提高性能。
虚拟DOM的优势包括:
提高性能:通过批量更新和最小化对真实DOM的操作,减少了浏览器的重绘和回流,从而提高了应用程序的性能。
跨平台:虚拟DOM是基于JavaScript对象的抽象,因此可以在不同平台上使用,例如浏览器、服务器端和移动端。
组件化开发:虚拟DOM与组件化开发相结合,可以将应用程序拆分为多个独立的组件,提高代码的可维护性和可重用性。
需要注意的是,虚拟DOM并不是解决所有性能问题的银弹。在某些情况下,直接操作真实DOM可能更加高效。虚拟DOM的使用需要权衡利弊,并根据具体情况进行选择。
虚拟dom的优缺点
优点:
提高性能:虚拟DOM通过批量更新和最小化对真实DOM的操作,减少了浏览器的重绘和回流,从而提高了应用程序的性能。
跨平台:虚拟DOM是基于JavaScript对象的抽象,因此可以在不同平台上使用,例如浏览器、服务器端和移动端。
组件化开发:虚拟DOM与组件化开发相结合,可以将应用程序拆分为多个独立的组件,提高代码的可维护性和可重用性。
简化开发:虚拟DOM使开发者能够以声明式的方式编写代码,通过模板语法描述组件的结构和属性,简化了开发过程。
缺点:
内存消耗:虚拟DOM需要在内存中构建和维护一个虚拟DOM树,这会占用一定的内存空间。对于大型应用程序或复杂的页面结构,虚拟DOM可能会导致较高的内存消耗。
初始渲染耗时:虚拟DOM需要在初始渲染时构建完整的虚拟DOM树,这可能会导致一定的渲染延迟。尤其是对于较大的应用程序或复杂的页面,初始渲染可能需要较长的时间。
vue组件之间的通信方式
父子组件之间的通信
兄弟组件之间的通信
祖孙与后代组件之间的通信
非关系组件间之间的通信
通过 props 传递 //父传子
通过 $emit 触发自定义事件 //子传父
使用 ref //子传父
EventBus //兄弟组件传值
$parent 或$root //兄弟组件传值(共同祖辈)
attrs 与 listeners
Provide 与 Inject //祖先传递数据给子孙
Vuex //状态管理工具
vue性能优化可以从哪些方面去做
keep-alive 缓存组件
路由懒加载
内容使用 v-if和v-show computed、watch、methods
Object.freeze :冻结对象 纯展示类的接口数据,冻结就可以了
使用ui组件按需引入
虚拟列表
es6常用
let const
箭头函数
1、简化了函数的写法
2、没有 this 机制,this 继承自上一个函数的上下文,如果上一层没有函数,则指向 window
3、作为异步回调函数时,可解决 this 指向问题
Promise
数组的方法
解构赋值
扩展运算符(...)等
跨域
跨域本质是浏览器基于同源策略的一种安全手段
同源策略(Sameoriginpolicy),是一种约定,它是浏览器最核心也最基本的安全功能
所谓同源(即指在同一个域)具有以下三个相同点
协议相同(protocol)
域名相同(host)
端口相同(port)
反之非同源请求,也就是协议、端口、域名其中一项不相同的时候,这时候就会产生跨域
解决跨域的方案
JSONP:JSONP是一种利用
<script>
标签跨域获取数据的技术。它通过在请求URL中添加一个回调函数名,服务器返回一段JavaScript代码,该代码会调用回调函数并传入数据作为参数。由于<script>
标签不受同源策略的限制,因此可以跨域获取数据。CORS:CORS是一种跨域资源共享的机制,它通过在服务器端设置响应头来允许跨域请求。具体来说,服务器可以在响应头中添加
Access-Control-Allow-Origin
字段来指定允许跨域请求的源,也可以添加其他字段来控制请求的方法、头信息等。代理:代理是一种通过服务器中转请求来实现跨域的方案。具体来说,前端可以将跨域请求发送给自己的服务器,服务器再将请求转发给目标服务器,并将响应返回给前端。由于跨域请求是在服务器之间进行的,因此不受同源策略的限制。
vue中一般使用代理,vue.config.js文件进行代理配置。
深拷贝和浅拷贝
浅拷贝,指的是创建新的数据,这个数据有着原始数据属性值的一份精确拷贝
如果属性是基本类型,拷贝的就是基本类型的值。如果属性是引用类型,拷贝的就是内存地址
即浅拷贝是拷贝一层,深层次的引用类型则共享内存地址
Object.assign
Array.prototype.slice()
,Array.prototype.concat()
使用拓展运算符实现的复制
深拷贝开辟一个新的栈,两个对象的属性完全相同,但是对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性
常见的深拷贝方式有:
_.cloneDeep()
jQuery.extend()
JSON.stringify()
手写循环递归
浅拷贝只复制属性指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存,修改对象属性会影响原对象
// 浅拷贝 const obj1 = { name : 'init', arr : [1,[2,3],4], }; const obj3=shallowClone(obj1) // 一个浅拷贝方法 obj3.name = "update"; obj3.arr[1] = [5,6,7] ; // 新旧对象还是共享同一块内存 console.log('obj1',obj1) // obj1 { name: 'init', arr: [ 1, [ 5, 6, 7 ], 4 ] } console.log('obj3',obj3) // obj3 { name: 'update', arr: [ 1, [ 5, 6, 7 ], 4 ] }但深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象
// 深拷贝 const obj1 = { name : 'init', arr : [1,[2,3],4], }; const obj4=deepClone(obj1) // 一个深拷贝方法 obj4.name = "update"; obj4.arr[1] = [5,6,7] ; // 新对象跟原对象不共享内存 console.log('obj1',obj1) // obj1 { name: 'init', arr: [ 1, [ 2, 3 ], 4 ] } console.log('obj4',obj4) // obj4 { name: 'update', arr: [ 1, [ 5, 6, 7 ], 4 ] }
闭包
一个函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起(或者说函数被引用包围),这样的组合就是闭包(closure)
也就是说,闭包让你可以在一个内层函数中访问到其外层函数的作用域
在
JavaScript
中,每当创建一个函数,闭包就会在函数创建的同时被创建出来,作为函数内部与外部连接起来的一座桥梁
创建私有变量
延长变量的生命周期
事件轮询
事件轮询是指JavaScript引擎在执行完当前任务后,会检查是否有待处理的事件,如果有,则立即处理这些事件,然后再继续执行其他任务。事件轮询的过程是不断循环的,直到所有的任务和事件都被处理完毕。
本地存储
Cookie、localStorage和sessionStorage
Cookie、localStorage和sessionStorage使用场景
Cookie
存储少量的用户信息,如用户ID、用户名等;
记录用户的浏览行为,如浏览历史、购物车等;
实现用户登录状态的保持,如记住密码等。
localStorage
存储用户的个性化设置,如主题、语言等;
缓存应用的静态资源,如图片、CSS、JS等;
存储应用的状态,如表单数据、用户输入等。
sessionStorage
存储临时数据,如表单数据、用户输入等;
缓存应用的动态数据,如AJAX请求的数据等;
存储应用的状态,如用户登录状态等。
tcp三次握手
1、第一次握手:客户端给服务器发送一个 SYN 报文。
2、第二次握手:服务器收到 SYN 报文之后,会应答一个 SYN+ACK 报文。
3、第三次握手:客户端收到 SYN+ACK 报文之后,会回应一个 ACK 报文。 服务器收到 ACK 报文之后,三次握手建立完成。