Vue + qiankun框架 样式混乱问题的解决办法

前言

qiankun 是一个基于 single-spa 的微前端实现库,旨在帮助大家更简单、无痛的构建一个生产可用微前端架构系统。关于什么是“微前端”,这里就不作过多介绍了,这里默认大家已经具有相关的预备知识。

对于qiankun如何与Vue结合,这篇博客里有详细介绍:基于qiankun的微前端接入笔记

问题与现象

子应用与父应用不断切换的过程中,子应用内的样式突然乱掉。

原因是子应用加载的<style>标签少了,导致遗失了样式。

(如果你检查DOM树发现没有出现这个现象,那有可能是父、子应用相互影响,建议参考官方文档,使用“样式隔离”参数进行解决)

解决

1)第一种修复函数

定义修复函数

/* main.js */
// 定义styleCount用于记录<style>标签数,styleList用于保存<style>节点对象
let styleCount = 0, styleList = []
// 定义一个修复函数
function fixStyleBug() {
  let qiankunStyles = document.querySelectorAll('div[data-qiankun="你的子项目名"] style');
  let len = qiankunStyles.length;
  if (styleCount < len) {
      console.log(`保存style数量:从${styleCount}变为${len}`);
      styleList = Array.from(qiankunStyles)
      styleCount = len
    } else if (styleCount > len) {
      let container = document.querySelectorAll('div[data-qiankun="你的子项目名"]')[0];
      qiankunStyles.forEach(style => { // 移除旧<style>
          container.removeChild(style);
      })
      styleList.forEach(style => { // 重新添加完整<style>
          container.appendChild(style);
      })
  }
}

调用修复函数进行修复

/* main.js */
// 在路由后置守卫里调用修复函数
router.afterEach(() => {
   fixStyleBug();
})

// 在挂载后调用修复函数
export async function mount(props) {
  fixStyleBug()
  render() // 渲染
}
第二种修复函数

定义修复函数

/* main.js */
// 定义styleCount用于记录<style>标签数,styleList用于保存<style>节点对象
let styleCount = 0, styleList = []
// 定义styleDisappearedRecord,表明styleList哪一段部分保存的是已丢失的<style>
let styleDisappearedRecord = {start: 0, end: 0};
function fixStyleBug() {
  let qiankunStyles = document.querySelectorAll('div[data-qiankun="你的子项目名"] style');
  let len = qiankunStyles.length;
  if (styleCount < len) {
      console.log(`保存style数量:从${styleCount}变为${len}`);
      let originalArr = Array.from(qiankunStyles) // 原始数组
      /* 
      调整丢失的<style>与框架新加的<style>的位置,使得丢失的<style>总是位于数组最后,以便与框架的dynamicStyleSheetElements数组保持对应
      即styleList = [...[未丢失样式], ...[新页面新增样式], ...[丢失样式]]  防止把要添加的<style>误加成新<style>
      */
      styleCount = len
      styleList = [...originalArr.slice(0, styleDisappearedRecord.start), ...originalArr.slice(styleDisappearedRecord.end), ...originalArr.slice(styleDisappearedRecord.start, styleDisappearedRecord.end)]
    } else if (styleCount > len) {
      let container = document.querySelectorAll('div[data-qiankun="你的子项目名"]')[0];
      styleDisappearedRecord.start = styleCount - len + 1;
      styleDisappearedRecord.end = styleCount
      styleList.forEach((style, index) => { // 丢失的样式都是从后面开始消失的,所以对比长度,添加上遗漏的
        if (index > len - 1) {
          console.log('添加:', style);
          container.appendChild(style);
        }
      })
  }
}

调用修复函数进行修复

/* main.js */
// 在路由后置守卫里调用修复函数
router.afterEach(() => {
   fixStyleBug();
})

// 在挂载后调用修复函数
export async function mount(props) {
  fixStyleBug()
  render() // 渲染
}

解释与分析

问题原因

实际上,样式乱掉的原因是因为,子应用加载的<style>标签少了,导致遗失了样式。

基本思路

解决这个问题的基本思路,就是我们自己帮它把丢失的<style>标签重新加上。

首先,我们需要知道“样式乱掉了“的时候,判断出这一现象已经发生。前面提到了,样式乱掉的原因在于<style>标签的减少。我们用一个styleCount来记下正常情况下的<style>标签数。再次加载子应用时,将styleCount与从DOM中读取的<style>标签数量进行对比,如果本次子应用加载的标签数比正常数少,那么就认为本次加载的子应用样式已经乱掉了。

其次,我们还需要事先保存下样式正常时的完整样式代码,即完整数量的<style>标签。我们用一个数组styleList将这些<style>节点保存下来即可。每次有新<style>标签增加,需要同步这个数组(确保styleList里保存的是最全、最完整的<style>标签)

当我们判断出本次加载子应用时<style>标签数减少了,就能判定样式存在丢失,接着从styleList这个数组里把丢失的<style>节点再次添加上去,这样遗失的样式就回来了,子应用里的样式也不会再乱了。

注意点

1)在点击子应用里之前未进入过的新页面时,是会增加<style>标签的。因此,需要在此时将框架新增的<style>也保存下来,保证我们的数组styleList是同步保存了全部的<style>标签。当然,标签数styleCount也要进行更新。

​ 因此才会在全局后置路由守卫里加入这个修复函数,以便进入页面时进行styleList、styleCount的更新。

2)修复函数一、修复函数二其实基本原理都是一样的。只是修复函数一是在检测到<style>标签丢失后,将DOM内的原标签全部删除(包括未遗失的),然后重新从styleList给DOM加上(这样就不用考虑具体遗失的是哪部分的标签)。属于比较暴力的方法。

​ 修复函数二是在一的基础上做的优化,不会删除DOM的原标签,只会把遗失的重新补上。但是比较麻烦的是,需要确保知道遗失的是哪部分的标签。这将有一个调整顺序的过程,具体的说明写在了代码注释里。
3)注意把代码里的

 document.querySelectorAll('div[data-qiankun="你的子项目名"]')

这些部分,把“你的项目名”,替换成你实际的子应用项目名。

结语

“我们不能解决问题,但是我们能解决出问题的人。”

目前还未找到<style>标签丢失的原因、以及出现这种现象的条件(极其没有规律)。相当于我们不知道问题在哪,所以也谈不上如何去解决问题本身。

但是换种思路,我们可以不去纠结“问题是怎么出现的”,我们可以把重点放在“如何避免这个现象”。只要样式不再次乱掉,用户用起来体验没影响,我们是可以勉强接受的。

解决不了<style>标签遗失这个问题,那就直接解决掉<style>标签。 ( ̄▽ ̄)"

如果有更好的修复办法,或者找到了这个现象的深层原因,欢迎指教!

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Vue3和qiankun都是目前前端领域非常流行的技术,它们可以在许多不同的场景下被应用。其中,Vue3是Vue框架的最新版本,它在设计之初就注重了性能和开发体验的优化,同时也增加了许多新功能,让开发者可以更加方便地构建高性能的web应用。而qiankun则是一款微前端框架,它可以让不同的团队开发自己的应用,并将它们集成到一个统一的页面中,以提高开发效率和应用的可维护性。 Vue3借助新的响应式数据结构可以大幅度提升渲染性能,同时也改进了一些语法和 API,更加符合现代开发的规范,易于上手和使用。Vue3在开发途中使用了编译时优化,还引入了定制化渲染器,使得开发者可以更加轻松地根据不同的业务需求进行个性化开发,而不影响整体性能。 qiankun则将多个微前端应用组装成一个整体,使用起来非常简单方便,并且具有高可扩展性和灵活性。它提供了诸如应用间通信、共享状态、应用隔离等功能,便于管理和维护多个应用之间的依赖关系和协作。此外,qiankun还支持热更新,可以在应用代码发生变更时,不影响整体部署的运行,提高了开发迭代速度。 综上所述,Vue3和qiankun分别从不同的角度出发,为前端开发者提供了高效、易用的开发工具。在实际应用中,可以根据业务场景的需要,将两者结合起来,构建出更具扩展性、可维护性和性能的web应用

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值