qiankun 微服务实现主题换肤

760 阅读1分钟

关注公众号: 微信搜索 前端工具人 ; 收货更多的干货

一、项目介绍

  • 主服务: 提供左侧导航;顶部快捷操作、用户信息、退出登录等
  • 多个子服务: 提供对应的业务功能
  • 前端微服务详细构建步骤和常见问题,可查看以往文章 https://juejin.cn/post/6943763969576271879

二、需求

为用户提供自定义换肤功能,页面对应的导航、svg、button、字体颜色...等等都要相应的切换

三、思路

  • 因为系统由多个服务共同构建,这种改变全局的操作肯定要放在主服务;

  • 通过主服务分发通知各个子服务, 进行相应的改变

    1. 主服务触发 setGlobalState 事件, 传递参数
    2. 各个子服务通过 onGlobalStateChange 事件接受参数

四、换肤方式

4.1. CSS 样式覆盖

  • 点击对应主题后给父节点增加不同的类名;
  • 不同主题下的各个组件样式各写一套;

4.2. css 文件替换

  • 点击对应主题后引入不同的主题css文件;
  • 不同主题下的各个组件样式各写一套且定义不同的文件;

4.3 css变量

  • 初始定义对应css变量
  • 点击对应主题后改变css变量

该篇文章使用的是 4.3

五、代码片段

5.1 主服务 variable.less

/* less css 变量
   $default-color 字体、icon、背景 颜色
   $border-color 边框色
   $background-hover-color  hover背景色
 */

:root {
  --default-color: #3B4966;
  --border-color: rgba(66, 81, 112, 0.6);
  --background-hover-color: rgba(66, 81, 112, 0.1);
}

// 页面样式
#app{
  // 上左侧边栏
  .layout-aside, .layout-header{
    background: var(--default-color);
  }
  // 按钮对应样式
  ...
  // 导航相关对应样式
  ...
}

5.2 主服务初始化css变量挂载到对应节点, 改变 css 变量 也是通过下面方法

[Types.SET_THEMES](state: VLayoutState, data: ITheme) {
    // 改变所挂载的变量
    document.getElementById('app').style.setProperty('--default-color', `#${data.value}`)
    document.getElementById('app').style.setProperty('--border-color', data.border)
    document.getElementById('app').style.setProperty('--background-hover-color', data.background)
}

5.2 主服务切换主题文件

const handelTheme = (item: ITheme) => {
  // .... 
  // 改变变量响应换肤
  store.dispatch(`layout/${Types.SET_THEMES}`, item)
  const theme = {
    value: '3B4966',
    border: 'rgba(66, 81, 112, 0.6)',
    background: 'rgba(66, 81, 112, 0.1)'
  }
  // 传递参数自由发挥
  globalStore.setGlobalState({
    activeTheme: theme
  })
}

5.3 子服务接收参数

注:

  1. 使用了 qiankun样式隔离则需求这一步, 由子服务自己更新主题
  2. 未使用样式隔离,则不需要下面这步, 统一由主服务更新主题, 样式层级需求高点,避免被子服务覆盖
// vue3 为例 main.ts (注册生命周期文件)
// ...
function storeTest(props) {
  props.onGlobalStateChange && props.onGlobalStateChange(
    (value, prev) => {
      // value 主服务传递过来的参数
      console.log(`[onGlobalStateChange - ${props.name}]:`, value, prev)
      store && store.dispatch(`layout/SET_THEMES`, value.activeTheme)
    },
    true
  );
}

有段时间没写博客了、文章写的比较粗糙;不知道有没有遗漏、有问题请留言;