获得徽章 0
赞了这篇文章
赞了这篇文章
为什么 Iframe 无法胜任微前端的工作?
IFrame 在传统的前端开发中是一种常见的技术,用于在页面中嵌入其他网页或应用程序。然而,在微前端架构中,IFrame 并不是一个理想的选择,主要是因为以下几个方面的限制:
隔离性和通信复杂性:IFrame 本身提供了一种隔离的环境,但这也带来了通信和数据交互的复杂性。由于每个子应用都在独立的 IFrames 中运行,它们之间的通信需要通过特定的机制,如消息传递,而这增加了开发和维护的复杂性。
性能和加载时间:每个 IFrames 都需要加载和渲染独立的 HTML、CSS 和 JavaScript。这意味着在加载微前端应用时,需要同时加载多个 IFrames,导致额外的网络请求和页面资源占用,可能会影响性能和加载时间。
样式和布局限制:IFrame 的内容在页面中是独立的,它们具有自己的 CSS 样式和布局上下文。这导致在微前端架构中难以实现全局样式的一致性,以及子应用之间的布局和交互的协调问题。
浏览器安全性限制:由于安全策略的限制,IFrame 之间的跨域通信可能受到限制,特别是在涉及跨域资源访问和共享数据时。这可能导致在微前端架构中需要处理复杂的安全性问题
IFrame 在传统的前端开发中是一种常见的技术,用于在页面中嵌入其他网页或应用程序。然而,在微前端架构中,IFrame 并不是一个理想的选择,主要是因为以下几个方面的限制:
隔离性和通信复杂性:IFrame 本身提供了一种隔离的环境,但这也带来了通信和数据交互的复杂性。由于每个子应用都在独立的 IFrames 中运行,它们之间的通信需要通过特定的机制,如消息传递,而这增加了开发和维护的复杂性。
性能和加载时间:每个 IFrames 都需要加载和渲染独立的 HTML、CSS 和 JavaScript。这意味着在加载微前端应用时,需要同时加载多个 IFrames,导致额外的网络请求和页面资源占用,可能会影响性能和加载时间。
样式和布局限制:IFrame 的内容在页面中是独立的,它们具有自己的 CSS 样式和布局上下文。这导致在微前端架构中难以实现全局样式的一致性,以及子应用之间的布局和交互的协调问题。
浏览器安全性限制:由于安全策略的限制,IFrame 之间的跨域通信可能受到限制,特别是在涉及跨域资源访问和共享数据时。这可能导致在微前端架构中需要处理复杂的安全性问题
展开
评论
点赞
堆与栈实际上是操作系统对进程占用的内存空间的两种管理方式,主要有如下几种区别:
(1)管理方式不同。栈由操作系统自动分配释放,无需我们手动控制;堆的申请和释放工作由程序员控制,容易产生内存泄漏;
(2)空间大小不同。每个进程拥有的栈的大小要远远小于堆的大小。理论上,程序员可申请的堆大小为虚拟内存的大小,进程栈的大小 64bits 的 Windows 默认 1MB,64bits 的 Linux 默认 10MB;
(3)生长方向不同。堆的生长方向向上,内存地址由低到高;栈的生长方向向下,内存地址由高到低。
(4)分配方式不同。堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是由操作系统完成的,比如局部变量的分配。动态分配由alloca函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由操作系统进行释放,无需我们手工实现。
(5)分配效率不同。栈由操作系统自动分配,会在硬件层级对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是由C/C++提供的库函数或运算符来完成申请与管理,实现机制较为复杂,频繁的内存申请容易产生内存碎片。显然,堆的效率比栈要低得多。
(6)存放内容不同。栈存放的内容,函数返回地址、相关参数、局部变量和寄存器内容等。当主函数调用另外一个函数的时候,要对当前函数执行断点进行保存,需要使用栈来实现,首先入栈的是主函数下一条语句的地址,即扩展指针寄存器的内容(EIP),然后是当前栈帧的底部地址,即扩展基址指针寄存器内容(EBP),再然后是被调函数的实参等,一般情况下是按照从右向左的顺序入栈,之后是被调函数的局部变量,注意静态变量是存放在数据段或者BSS段,是不入栈的。出栈的顺序正好相反,最终栈顶指向主函数下一条语句的地址,主程序又从该地址开始执行。堆,一般情况堆顶使用一个字节的空间来存放堆的大小,而堆中具体存放内容是由程序员来填充的。
从以上可以看到,堆和栈相比,由于大量malloc()/free()或new/delete的使用,容易造成大量的内存碎片,并且可能引发用户态和核心态的切换,效率较低。栈相比于堆,在程序中应用较为广泛,最常见的是函数的调用过程由栈来实现,函数返回地址、EBP、实参和局部变量都采用栈的方式存放。
(1)管理方式不同。栈由操作系统自动分配释放,无需我们手动控制;堆的申请和释放工作由程序员控制,容易产生内存泄漏;
(2)空间大小不同。每个进程拥有的栈的大小要远远小于堆的大小。理论上,程序员可申请的堆大小为虚拟内存的大小,进程栈的大小 64bits 的 Windows 默认 1MB,64bits 的 Linux 默认 10MB;
(3)生长方向不同。堆的生长方向向上,内存地址由低到高;栈的生长方向向下,内存地址由高到低。
(4)分配方式不同。堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是由操作系统完成的,比如局部变量的分配。动态分配由alloca函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由操作系统进行释放,无需我们手工实现。
(5)分配效率不同。栈由操作系统自动分配,会在硬件层级对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是由C/C++提供的库函数或运算符来完成申请与管理,实现机制较为复杂,频繁的内存申请容易产生内存碎片。显然,堆的效率比栈要低得多。
(6)存放内容不同。栈存放的内容,函数返回地址、相关参数、局部变量和寄存器内容等。当主函数调用另外一个函数的时候,要对当前函数执行断点进行保存,需要使用栈来实现,首先入栈的是主函数下一条语句的地址,即扩展指针寄存器的内容(EIP),然后是当前栈帧的底部地址,即扩展基址指针寄存器内容(EBP),再然后是被调函数的实参等,一般情况下是按照从右向左的顺序入栈,之后是被调函数的局部变量,注意静态变量是存放在数据段或者BSS段,是不入栈的。出栈的顺序正好相反,最终栈顶指向主函数下一条语句的地址,主程序又从该地址开始执行。堆,一般情况堆顶使用一个字节的空间来存放堆的大小,而堆中具体存放内容是由程序员来填充的。
从以上可以看到,堆和栈相比,由于大量malloc()/free()或new/delete的使用,容易造成大量的内存碎片,并且可能引发用户态和核心态的切换,效率较低。栈相比于堆,在程序中应用较为广泛,最常见的是函数的调用过程由栈来实现,函数返回地址、EBP、实参和局部变量都采用栈的方式存放。
展开
评论
点赞
ref做了什么?
调用ref将 定义的数据传入,返回一个创建ref响应式数据的函数,是否需要浅层复制,默认为false,也就意味着一定会走 转换成 reactive
调用createRef, 判断是否 是一个 ref对象 ,是 原值返回 否则 , new 一个 实现ref类
创建类的私有变量 ,保存传入的value 和 shallow
判断是否浅层复制,如果是则 返回传入的 value,否则取出 ref的原始值对象
获取值的时候将 保存的值 返回 出去
设置值的时候 判断当前属性 是否是浅层对象 ,如果是 则返回该数据 否则 调用 toreactive转换 reactive 进行操作
触发更新
调用ref将 定义的数据传入,返回一个创建ref响应式数据的函数,是否需要浅层复制,默认为false,也就意味着一定会走 转换成 reactive
调用createRef, 判断是否 是一个 ref对象 ,是 原值返回 否则 , new 一个 实现ref类
创建类的私有变量 ,保存传入的value 和 shallow
判断是否浅层复制,如果是则 返回传入的 value,否则取出 ref的原始值对象
获取值的时候将 保存的值 返回 出去
设置值的时候 判断当前属性 是否是浅层对象 ,如果是 则返回该数据 否则 调用 toreactive转换 reactive 进行操作
触发更新
展开
评论
点赞
前端和后端开发的区别:
服务稳定性:
server 端可能会遭受各种恶意攻击和误操作
单个客户端可以意外挂掉,但是服务端不能
考虑 CPU 和内存(优化、扩展):
客户端独占一个浏览器,内存和 CPU 都不是问题
server 端要承载很多请求,CPU 和内存都是稀缺资源
日志记录:
前端也会参与写日志,但只是日志的发起方,不关心后续
server 端要记录日志、存储日志、分析日志,前端不关心
安全:
server 端要随时准备接收各种恶意攻击,前端则少很多
如:越权操作,数据库攻击等
集群和服务拆分:
产品发展速度快,流量可能会迅速增加
如何通过扩展机器和服务拆分来承载大流量?
服务稳定性:
server 端可能会遭受各种恶意攻击和误操作
单个客户端可以意外挂掉,但是服务端不能
考虑 CPU 和内存(优化、扩展):
客户端独占一个浏览器,内存和 CPU 都不是问题
server 端要承载很多请求,CPU 和内存都是稀缺资源
日志记录:
前端也会参与写日志,但只是日志的发起方,不关心后续
server 端要记录日志、存储日志、分析日志,前端不关心
安全:
server 端要随时准备接收各种恶意攻击,前端则少很多
如:越权操作,数据库攻击等
集群和服务拆分:
产品发展速度快,流量可能会迅速增加
如何通过扩展机器和服务拆分来承载大流量?
展开
评论
点赞
赋值和浅拷贝的区别
当我们把一个对象赋值给一个新的变量时,赋的其实是该对象的在栈中的地址,而不是堆中的数据。也就是两个对象指向的是同一个存储空间,无论哪个对象发生改变,其实都是改变的存储空间的内容,因此,两个对象是联动的
浅拷贝是按位拷贝对象,它会创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值;如果属性是内存地址(引用类型),拷贝的就是内存地址 ,因此如果其中一个对象改变了这个地址,就会影响到另一个对象。即默认拷贝构造函数只是对对象进行浅拷贝复制(逐个成员依次拷贝),即只复制对象空间而不复制资源
当我们把一个对象赋值给一个新的变量时,赋的其实是该对象的在栈中的地址,而不是堆中的数据。也就是两个对象指向的是同一个存储空间,无论哪个对象发生改变,其实都是改变的存储空间的内容,因此,两个对象是联动的
浅拷贝是按位拷贝对象,它会创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值;如果属性是内存地址(引用类型),拷贝的就是内存地址 ,因此如果其中一个对象改变了这个地址,就会影响到另一个对象。即默认拷贝构造函数只是对对象进行浅拷贝复制(逐个成员依次拷贝),即只复制对象空间而不复制资源
展开
评论
点赞
Vue的生命周期
·beforeCreate:实例刚在内存中被创建,此时尚
未初始化各项数据。
·created:实例已经创建完成,数据已初始化,但
尚未编译模板。
·beforeMount:模板编译/挂载之前调用,此时尚
未生成DOM节点。
·mounted:模板编译/挂载完成,DOM节点已经生
成,可以进行DOM操作。
·beforeUpdate:数据更新之前调用,此时可以对
数据进行一些处理。
·updated:数据更新完成,DOM重新渲染。
·beforeDestroy:实例销毁之前调用,可以进行一些清理工作。
·destroyed:实例销毁完成,清理工作已完成。
·beforeCreate:实例刚在内存中被创建,此时尚
未初始化各项数据。
·created:实例已经创建完成,数据已初始化,但
尚未编译模板。
·beforeMount:模板编译/挂载之前调用,此时尚
未生成DOM节点。
·mounted:模板编译/挂载完成,DOM节点已经生
成,可以进行DOM操作。
·beforeUpdate:数据更新之前调用,此时可以对
数据进行一些处理。
·updated:数据更新完成,DOM重新渲染。
·beforeDestroy:实例销毁之前调用,可以进行一些清理工作。
·destroyed:实例销毁完成,清理工作已完成。
展开
评论
点赞
面试
有没有和我一样想法的姐妹