SingleSpa微前端基本使用以及原理

先说说singleSpa的缺点

  • 不够灵活 不能动态加载css文件
  • css不隔离
  • 没有js沙箱的机制 ( 没有全局对象 每次切换的应用 都是同一个window )

但是刚刚接触微前端 可以了解一下微前端的基础使用
qiankun微前端框架已经很成熟 也是基于singleSpa来实现的
点击跳转qiankun的基础使用

大致实现思路 (不了解微前端概念的可以去自行了解)

  • 首先在父应用注册一个应用
  • 当条件满足的时候(匹配路径) 会加载我们另一个子应用的脚本
  • 加载子应用用脚本的话
    – 那在我们子应用打包的时候 , 自身上就有一些类库了
  • 父应用加载到子应用的类库时候 就会调用子应用身上的一些方法了
    – 这个时候 类库就会把子应用整体的dom 放在( 挂载 )到父应用上面去
  • 而且我们要保证子应用自身引用的所有路径 都是相对于自身的绝对路径
    – 不然在父应用里使用子应用的一些操作 调用的是父应用的根路径 就会出问题

首先创建两个应用

一个子应用 各个父应用

在这里插入图片描述

我们需要父应用加载子应用 需要在子应用导出三个方法
bootstrap mount unmount ( SingleSpa的规定 )

vue的项目需要npm安装 Single-spa-vue
react的项目需要npm安装 Single-spa-react

初始化子应用

npm安装single-spa-vue

  • 配置main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'

// 引入singleSpaVue的包
import singleSpaVue from 'single-spa-vue'
Vue.config.productionTip = false


//子应用不能直接挂载
// new Vue({   
//   router,
//   render: h => h(App)
// }).$mount('#app')

// 而是封装成一个对象
const appOptions = {
    el:'#vue',  // 增加一个属性挂在到父应用的 id为vue的标签上
    router,
    render: h => h(App)
}

// 把vue和上面这个对象传入进去  这个singleSpaVue就会返回vueLife
// vueLife是包装好的生命周期  对应的就是bootstrap mount unmount  这三个方法
const vueLife = singleSpaVue({
  Vue,
  appOptions
})

//导出这三个方法  
//协议接入  我定好了这些方法  父应用会调用这些方法
export const bootstrap = vueLife.bootstrap
export const mount = vueLife.mount
export const unmount = vueLife.unmount
  • 我们需要父应用加载子应用 需要打包成一个个的lib去给父应用使用
  • 如何打包呢 在vue.config.js中配置
module.exports = {
  configureWebpack:{
    output:{
       // 给类库取一个名字
      library:'singleVue',
      // 指定模块类型  umd 会把打包后那三个属性挂在window上 
      //比如 window.bootstrap / window.mount / window.oumount
      libraryTarget:'umd' 
    },
    devServer:{
      port:10000 
    }
  }
}

初始化父应用

npm安装single-spa (不要加vue)

  • App.vue中处理结构
<template>
  <div id="app">
    <!-- 路由中没写/vue这个路径  说明路由匹配不到  但是可以去匹配这个路由来加载子应用  -->
    <router-link to="/vue">加载vue子应用</router-link>
    <!-- 这个id = vue就是子应用main.js中el挂载的#vue -->
    <div id="vue"></div>
  </div>
</template>
  • main.js处理
import Vue from 'vue'
import App from './App.vue'
import router from './router'
// 固定导出两个方法  注册应用 / 开始应用
import {registerApplication,start} from 'single-spa'
Vue.config.productionTip = false

// 注册应用  参数1 注册一个名字  参数2 一点要是个promise函数
registerApplication('myVueApp',
    async()=>{
      // 如果路径为 /vue  就会调用现在这个方法了   但是这个方法必须要导出子应用下的那三个方法 (不导出会报错) 
      // 但是这个三个方法在哪里呢  请看下面的图片 具体写法先写如下
      // 动态创建script标签 把这个模块引入进来  (加载顺序要先加载公共的  再加载自己的 )
      await loadScript('http://localhost:10000/js/chunk-vendors.js')
      await loadScript('http://localhost:10000/js/app.js')
      // 这样就可以导出window上的lib包了  'singleVue'就是vue.config.js配置的包名 
      return window.singleVue //bootstrap mount onmount
      
    },
    // 参数3 用户切换到/vue路径下 需要加载刚刚定义的子应用
    location=>location.pathname.startsWith('/vue')
)

// 处理上面参数2的promise
async function loadScript(url){
  // js加载是异步的 所以要用promise
  return new Promise((resole,reject)=>{
    let script = document.createElement('script')
    script.src = url
    script.onload = resole // 加载成功
    script.onerror = reject //加载失败
    document.head.appendChild(script) //把script放在html的head标签里 
  })
}

// 开启应用
start()


new Vue({
  router,
  render: h => h(App)
}).$mount('#app')

在这里插入图片描述

  • 这样就开启了基础的嵌入子应用
    在这里插入图片描述
  • 点击按钮后 ( 但是还有问题 )
  • css没有隔离 ( 使用到了子应用的css 导致标签就居中了 )
  • 点击子应用的路由 跳转会错误
    – 路径上的/vue会消失( 点击子应用的路由 但是跳转的是父应用的路由 )
    – 需要在子应用中虚拟一个路径
    在这里插入图片描述

给子路由配置基础路径

  • 子应用的router/index中
const router = new VueRouter({
  mode: 'history',
  // base: process.env.BASE_URL, //删除原本的
  //点击子应用的路由的时候 需要通过/vue去加载
  base: '/vue', 
  routes
})
  • 但是还有个问题 每次点击子路由的时候 加载的是父应用上的路由
    – 我们需要操作子应用的时候 匹配的是子应用自身的路径
    – 解决方法 : 我们请求的每一个路由 都要加载的是自身的根路径才行
    -在子应用的main.js中配置
    主要看if(window.singleSpaNavigate){}后面的新增代码
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import singleSpaVue from 'single-spa-vue'
Vue.config.productionTip = false


const appOptions = {
    el:'#vue',  
    router,
    render: h => h(App)
}

const vueLife = singleSpaVue({
  Vue,
  appOptions 
})

//加上了如下的判断
//如果父应用引用我的时候
if(window.singleSpaNavigate){
  // 动态的设置一个属性 打包的时候加上一个目录 目录就是自身的根路径
  // 这样的时候我们发请求的时候 都会把这个路径拼到最前面 变成一个绝对路径
  __webpack_public_path__ = 'http://localhost:10000/'
}
//我们还需要让子应用独立运行 (如果父应用没有引用我的时候)
if(!window.singleSpaNavigate){
  // 子应用独立运行的话 就是正常初始化vue了  这个挂载父应用的el就可以删除
  delete appOptions.el
  //可以正常初始化vue了  
  new Vue(appOptions).$mount('#app')
}

export const bootstrap = vueLife.bootstrap
export const mount = vueLife.mount
export const unmount = vueLife.unmount

现在的话已经基础的实现了父应用嵌套子应用

并且子应用也可以独立运行了

在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/453407.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Vuforia+Unity】一个简单AR识别图像弹出按钮播放暂停视频

场景搭建 2.按钮播放视频这部分写一个按钮回调函数即可 3.控制视频的代码 using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Video;public class videomanager : MonoBehaviour {// 这个脚本实现按钮控制VIDEO播放GameO…

snakeflow的springboot项目

Gitee搜索“liuxz/snakerflow”&#xff0c;它是spring boot集成了一款国产工作流引擎snakerflow。 下面是安装步骤&#xff1a; 创建数据库snaker-web&#xff0c;字符集设置成utf8mb4和utf8mb4_generic。不然的话&#xff0c;中文插入不进去。 运行sql命令 CREATE TABLE …

算法刷题day29:区间合并

目录 引言概念一、挤牛奶二、区间合并三、校门外的树四、管道 引言 区间合并这种题&#xff0c;是比较小的题&#xff0c;一般是不会直接出成一道题来考你的&#xff0c;一般思路都是给一道题&#xff0c;里面包含了各种的点&#xff0c;每一个点都需要一个想区间合并这样的知…

【代表作神刊】经管社科类,稀缺SSCI2区期刊,仅14天见刊,2天检索!!

2024年3月第二周&#xff0c;我处EA-ISET协会推荐发表的文章目前都在有序进行中&#xff0c; 新增检索5篇&#xff0c;SSCI5篇&#xff1b; 新增见刊10篇&#xff0c;SSCI1篇&#xff0c;CNKI5篇&#xff0c;谷歌普刊4篇&#xff1b; 现整理部分录用案例&#xff0c;时间节点…

新书速览|机器学习实战:视频教学版

掌握线性回归、分类、数据降维、聚类、关联规则、协同过滤算法及应用 本书内容 《机器学习实战&#xff1a;视频教学版》基于Python语言详细讲解机器学习算法及其应用&#xff0c;用于读者快速入门机器学习。本书配套示例源代码、PPT课件、教学视频、教学大纲、习题与答案、作者…

Voip测试工具

SIPp是一个测试SIP协议性能的工具软件。这是一个GPL的开放源码软件。 sipp是安装在linux机器上的 SIPp可以用来测试许多真实的SIP设备&#xff0c;如SIP代理&#xff0c;B2BUAs,SIP媒体服务器&#xff0c;SIP/x网关&#xff0c;SIP PBX&#xff0c;等等&#xff0c;它也可以模…

for、while、do...while循环的使用

本篇文章只记录for、while、do...while循环的使用&#xff0c;由于java循环较为简单&#xff0c;所以直接上代码。 1、for循环 需求&#xff1a;循环遍历求和 1-100。 public class Demo {public static void main(String[] args) {int sum 0;for (int i 1; i < 100; i…

技术驱动校园招聘:Java+SpringBoot+Vue的实践之旅

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

Linux——线程(2)

在上一篇博客中我介绍了Linux中的线程是什么样的&#xff0c;就如同进程可以通过 fork创建&#xff0c;可以被终止&#xff0c;可以退出一样&#xff0c;线程也可以被我们用户控制&#xff0c;这 篇博客我会介绍线程的控制&#xff0c;并且基于线程的控制所产生的一些问题进行 …

麒麟信安集控云工作站解决方案,驱动电网奔向数字化转型新未来!

集控站是电网运行信息的集中监控中心&#xff0c;实现对电网设备状态感知、缺陷发现、主动预警、风险管控和应急处置的全流程闭环管控&#xff0c;在保障日常供电方面发挥重要作用。此前集控站主要采用网络KVM矩阵&#xff0c;其数字化转型面临延长距离受限、无法实现跨辖区延伸…

Redis及其常用命令(二)

SortedSet类型 在此类型中&#xff0c;每个元素都有一个分数 key -> string value -> sorted([socre,member],[score,member]...) # 添加元素 zadd key score member # 遍历集合 zrange key start stop [withscores] #升序 zrevrange key start stop [withscores]#降序…

二、vue-cli项目搭建

系列文章&#xff1a; vue实战&#xff08;商城后台管理系统&#xff09;&#xff1a;http://t.csdnimg.cn/f6Fqa vue.js :http://t.csdnimg.cn/mljxv 目录 系列文章&#xff1a; vue实战&#xff08;商城后台管理系统&#xff09;&#xff1a;http://t.csdnimg.cn/f6Fqa vue…

O2OA(翱途)流程引擎中如何修改,定制流程的流转记录

使用场景 在特殊使用场景中需要定制流转记录,比如业务上需要修改用户名称,修改时间和意见等. 比如一下场景: 需要将用户"b(company01)"的流转记录修改为"d(company01)". 手工修改 系统默认提供维护工具,在有权限的情况下可以直接进行维护. 通过"左…

AI壁纸号一周增加上千粉丝,轻松变现的成功案例分享

前言 随着AI绘画技术的发展&#xff0c;传统的互联网副业壁纸号在新的技术加持下迎来了第二春。本文将分享一位壁纸号创作者的成功案例&#xff0c;并为大家提供创作门槛和硬件要求等相关信息。 该项目的创作门槛极低&#xff0c;基本上可以由AI完成内容创作。不过&#xff0…

“我快无聊死了”用英语怎么说?柯桥英语口语学习,成人零基础学外语

每日一句 Im bored to death. 我快无聊死了。 单词解析&#xff1a; bored / bɔːd / adj.无聊的&#xff0c;厌倦的 bored to d15857575376eath&#xff1a;指非常无聊或厌烦&#xff0c;达到了极点的程度。 "bored" 和 "boring" 都与无聊相关&#…

Python编程从入门到实践中的一些误区

1.num 使用num时python报错&#xff0c;后来查过后才知道是因为python不支持自增或自减&#xff0c;可以用1。 2.字符串和非字符串连接 要先将非字符串转换为字符串类型之后才能连接 print&#xff08;2int&#xff08;‘2’&#xff09;&#xff09;#4 3.关键字参数必须在未…

基于springboot+vue的电子商务系统(源码+论文)

目录 前言 一、功能设计 二、功能实现 三、库表设计 四、论文 前言 各种购物网站现在已经成了生活中不可缺少的调味品,比如比较全面的淘宝网,还有可以进行交流问答的小红书APP,还有电脑爱好者者们的天堂京东商城等等。拥有一个功能丰富、操作方便的电子商务销售网站,可以汇…

jenkins部署go应用 基于docker-compose

丢弃旧的的构建 github 拉取代码 指定go的编译版本 编写docker-compose 文件 docker-compose.yaml version: "3"services:game-api:image: centos:7working_dir: /appcontainer_name: game-api #自定义command: "./game-api -f conf/config.yaml"por…

针对二进制储存方式深度解析

int main() { int a[4] { 1, 2, 3, 4 }; int* p1 (int*)(&a 1); int* p2 (int*)((int)a 1); printf("%x %x", p1[-1], *p2); return 0; } X86环境下运行 %x打印16进制。 整形指针1跳过四个字节&#xff0c;((int)a 1)强制类型转换为…

【记录 | 基础动态规划】:数字三角形

数字三角形 链接:[USACO1.5] [IOI1994]数字三角形 Number Triangles 题目描述 观察下面的数字金字塔。 写一个程序来查找从最高点到底部任意处结束的路径,使路径经过数字的和最大。每一步可以走到左下方的点也可以到达右下方的点。 在上面的样例中,从 7 → 3 → 8 → 7 →…