企业🤖AI Agent构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
## iframe 用途: 用于嵌入第三方资源,比如广告、视频或音频等等。使用iframe可以保证页面代码的简洁,还能让文挡之间有隔离不用担心相互之间有影响 >src 指定网页的地址 >width 内嵌网页的宽度 >heigth 内嵌网页的高度 >frameborder 0 /1 表示是否显示边框(0为否) >scrolling yes/or/auto 是否显示滚动条 >id 为框架的唯一标识 >name 会和标签中的name相互对应 ```js // name属性;通常和target搭配使用 <a href="https://www.baidu,com" target = "chaungkou">baidu</a> <a href="https://www.jianshu,com" target = "chaungkou">jianshu</a> <iframe id="Myframe" name="chaungkou"></iframe> /*这样就实现了两个a标签点击后都只在一个iframe中呈现了*/ ``` ### **iframe的优缺点** 优点 > 解决加载缓慢的第三方内容如图标和广告等的加载问题 > 能并行加载脚本 > 方便管理,指的是如果有多个页面需要用到iframe的内容,那么只要修改iframe的内容就可以实现统一管理 > iframe可以原封不动的把嵌入的网页显示出来 **加载其他域的网页** iframe是允许跨域请求资源的,但是不能够修改,由此可以在网页中嵌套其他网页,如需要跨域通信的话,需要考虑document.domain、window.name、window.postMessage 若需要**刷新**iframe则只需要刷新框架内,不需要刷新整个页面 **缺点** 不利于SEO,搜索引擎的爬虫无法解读iframe的页面。 iframes阻塞页面加载,影响网页加载速度,iframe加载完毕后才会触发window.onload事件,动态设置src可解决这个问题。 iframe和主页面共享连接池,而浏览器对相同域的连接有限制,所以会影响页面的并行加载,也就是说子文档和父文档的请求数会被计算在一起 ### **iframe 跨域与通信** 1. document.domain+iframe的设置 document.domain,这是浏览器暴露出来的一个准只读属性(之所以说它是准只读属性,是因为它可以设置为当前域名的超级域),利用这个特性,可以实现主域名相同子域名不同的网页实现通信。 2. 使用HTML5 postMessage HTML5提供的API,可以安全的启用跨域通信。 语法:targetWindow.postMessage(data, targetOrigin),data参数是指要传递的数据。 如何在目标窗口接收到数据呢? ```js window.addEventListener('message', function(evt) { console.log(evt.data); }, false); // evt.data即是postMessage中传递过来的数据。 ``` # qiankun https://blog.csdn.net/qq_41694291/article/details/113842872 **qiankun 特性** > - 基于 single-spa 封装,提供了更加开箱即用的 API。 > - 技术栈无关,任意技术栈的应用均可使用/接入,不论是 React/Vue/Angular/JQuery 还是其他等框架。 > - HTML Entry 接入方式,让我们接入微应用像使用 iframe 一样简单。 > - 样式隔离,确保微应用之间样式互相不干扰。 > - JS 沙箱,确保微应用之间 全局变量/事件 不冲突。 > - 资源预加载,在浏览器空闲时间预加载未打开的微应用资源,加速微应用打开速度。 > - umi 插件,提供了 @umijs/plugin-qiankun 供 umi 应用一键切换成微前端架构系统。 qiankun是基于基座模式的,所以它必然有一个基座应用(主应用),来管理各个子应用的加载和卸载。 微前端需要解决: - **应用的加载与切换( single-spa[路由问题、应用入口]、应用加载)**; - **应用的隔离与通信( js隔离、css样式隔离、应用间通信)** * * **路由问题** * single-spa是监听hashChange和popState来检测路由变化的,劫持原生的pushState和replaceState事件 * * **应用入口** * 应用入口必须暴露出bootstrap、mount、unmount三个生命周期钩子函数且返回Promise,以保证single-spa可以注册回调函数。 * bootstrap--挂载前的准备, 在子应用的`bootstrap`钩子内手动创建这样一个节点并插入到基座应用 * * **采用快照策略实现js隔离** * 在加载应用前,将window上的所有属性保存起来(即拍摄快照);等应用被卸载时,再恢复window上的所有属性。IE下的快照策略无法支持多实例模式。 qiankun通过import-html-entry,可以对html入口进行解析,并获得执行脚本的方法execScripts。qiankun引入该接口后,首先为该应用生成一个window的代理对象,然后将代理对象作为参数传入接口,以保证应用内的js不会对全局window造成影响。 * * **css样式隔离** * 两种样式隔离方案,一种是基于shadowDom隔离,即为子应用的根节点创建一个shadow root。最终整个应用的所有DOM将形成一棵shadow tree。它内部所有节点的样式对树外面的节点无效。 缺陷:弹出框直接挂载到document.body下,脱离了shadow tree,它的样式仍会对全局造成污染。 ```js sandbox: { strictStyleIsolation: true // experimentalStyleIsolation: true // 实验性方案,scoped方式 }, ``` * 另一种则是实验性的,思路类似于Vue中的scoped属性,给每个子应用的根节点添加一个特殊属性,用作对所有css选择器的约束。不支持@ keyframes,@ font-face,@ import,@ page(即不会被重写) * * **应用间通信** * 基于一个全局的globalState对象。这个对象由基座应用负责创建,内部包含一组用于通信的变量,以及两个分别用于修改变量值和监听变量变化的方法:setGlobalState和onGlobalStateChange。 ```js // 在基座应用中初始化 import { initGlobalState, MicroAppStateActions } from 'qiankun'; const initialState = {}; const actions: MicroAppStateActions = initGlobalState(initialState); export default actions; // 加载子应用时通过props将actions传递到子应用内, actions.onGlobalStateChange(globalState, oldGlobalState){} // 监听全局状态变化 actions.setGlobalState(...); // 修改全局状态 ``` ## qiankun实践 安装:`$ yarn add qiankun # 或者 npm i qiankun -S` - **在主应用中注册微应用** ```js // 微应用入口配置 micro-app.js const microApps: Array<any> = [{ name: 'module-app1', entry: 'https://app1.example.com', activeRule: '/app1', container: '#root-view', sandbox: { strictStyleIsolation: true } // 开启样式隔离 }, { name: 'module-shop', entry: 'https://app2.example.com', activeRule: '/app2', container: '#root-view', sandbox: { strictStyleIsolation: true } // 开启样式隔离 }, ...]; export default microApps; ``` 当微应用信息注册完之后,一旦浏览器的 url 发生变化,便会自动触发 qiankun 的匹配逻辑,所有 activeRule 规则匹配上的微应用就会被插入到指定的 container 中,同时依次调用微应用暴露出的生命周期钩子。 如果微应用不是直接跟路由关联的时候,可手动加载微应用的方式: ```js import { loadMicroApp } from 'qiankun'; loadMicroApp({name:'app', entry:'//localhost:7100', container:'#yourContainer'}); ``` **现在希望在加载左侧菜单栏的时候去注册和启动qiankun** ```js // menu.vue <script> import {registerMicroApps, start} from 'qiankun'; // 引入注册子应用和启动的接口函数 import microApps from './modules/micro-apps'; // 引入微应用入口配置 export default class PrimeMenu extends Vue { async created () { // 注册一些全局生命周期钩子,如进行日志打印,不需要可不传 registerMicroApps(microApps, { beforeMount () {} }); start({ prefetch: true }); // 启动qiankun,并开启预加载 } } </script> ``` 路由变化触发hashChange事件,而qiankun借助single-spa所绑定的监听事件,会侦测到地址变化而执行reroute函数; 随后qiankun通过import-html-entry提供的能力,去下载app1对应的html文件,并从中解析出所依赖的脚本和样式文件。 qiankun会将其封装在一个沙箱中,执行这些脚本并添加样式表,从而渲染出子应用。 ```js window.history.pushState({}, '', '/app1/overview'); window.location.href = '/app1/overview'; ``` - **微应用(以vue框架为例)** 子应用内暴露出三个生命周期钩子函数:bootstrap、mount、unmount ```js let router = null; let instance = null; function render(props = {}) { const { container } = props; router = new VueRouter({ base: window.__POWERED_BY_QIANKUN__ ? '/app-vue/' : '/', mode: 'history', routes, }); instance = new Vue({router,store,render: (h) => h(App),}) .$mount(container ? container.querySelector('#app') : '#app'); } if (window.__POWERED_BY_QIANKUN__) { // 在qiankun环境下,修正加载路径 __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__; } else { render(); } // 独立运行时 export async function bootstrap() { console.log('[vue]vueapp bootstraped');} export async function mount(props) { console.log('[vue]props from main', props); render(props); } export async function unmount() { instance.$destroy(); instance.$el.innerHTML = ''; instance = null; router = null; } ``` 打包配置修改(vue.config.js) ```js const { name } = require('./package'); module.exports = { devServer: { headers: { 'Access-Control-Allow-Origin': '*' } }, configureWebpack: { output: { library: `${name}-[name]`, libraryTarget: 'umd', // 把微应用打包成 umd 库格式 jsonpFunction: `webpackJsonp_${name}`, }, }, }; ``` umd格式的应用会向外暴露指定的生命周期钩子函数,便于single-spa解析。 jsonpFunction配置是webpack打包之后保存在window中的key,只需保证各个子应用不一致即可。