Umi微前端水印踩坑以及解决方案

最近公司需要在管理后台加一个水印方案~ 项目用的umi方案,以为就是改一个配置的问题,后来发现坑点还蛮多~ 希望此稳定能帮助到用umi 的你们.

一. 先来说说心路历程

坑点1

umi的水印适配只能在layout中进行配置,也就是路由配置中layout为false的页面无法配置水印,比如说登录页~
在这里插入图片描述

坑点2

就算只对layout配置也会有问题,如下是配置与效果
请添加图片描述
可以看到头部区域,菜单区域以及空白区域适配不到.
请添加图片描述

坑点3

既然配置不好处理,而umi用的是react的ant组件,那是不是可以用ant的水印组件Watermark去包裹根组件达到效果呢?
想法是好的. 实际情况是umi的app.tsx只是一个配置文件,它并没有暴露根组件,也就是说我们只能用原生js拿到根节点~ 但就算拿到根节点,你又如何去适配Watermark组件呢? 原生与jsx如何进行写法上的兼容?
请添加图片描述

坑点4

因为以上诸多不便,我不得不尝试寻找其它可替代方案. 比如去github上寻找原生相关的水印方案库~ 反复查找下锁定了一个start比较多的开源水印库:watermark-dom
这个库的优点是简单易用,对水印有保护策略的加持; 缺点是最新版本更新与2019年,对ts的兼容性不是很好,水印内容只能文本不能是图片,且适配不是很好,不能随着内容变化而变化,还会出现滚动条等问题~
所以这个库我们只能作为备选方案…

心路总结

基于以上心路,最后决定还是回到坑点3,尝试手动适配

二. 核心解决思路

  1. 通过react18的createRoot,render出水印组件对应的dom
  2. 通过MutationObserver监听dom的变化,并在异步回调中做处理
  3. 拿到水印dom之后将其append到masteroot根节点之中
  4. 存储水印文案,判断是否变化.
  5. 变化了的话重复1步骤render创建水印,删除旧的水印,append新的水印dom
  6. 最后通过observer.disconnect()注销监听

三. 实现代码

如下是我的最终调试代码,在app.tsx文件中调用即可

import { Watermark } from 'antd';
import { createRoot } from 'react-dom/client';
let oldval: string = '';
const creatWatermark = (content: string) => {
  console.log(oldval, content);
  if (oldval && oldval === content) return;
  const opt = {
    content: content,
    fontColor: 'red',
    fontStyle: 'normal',
    fontSize: 23,
    gapX: [30, 30],
    rotate: 10,
  };
  oldval = content;
  // 选择需要观察变动的节点
  const targetNode = document.createElement('div');
  // 解析AST&挂载(是异步,所以后续需要监听节点变化再做处理)
  createRoot(targetNode).render(<Watermark {...opt} />);
  // 观察器的配置(需要观察什么变动, childList只能向下观察到一级, subtree可多级 )
  const config = { childList: true, subtree: true };
  // 当观察到变动时执行的回调函数
  const callback = (
    mutationsList: MutationRecord[],
    observer: MutationObserver,
  ) => {
    for (let mutation of mutationsList) {
      if (mutation.type === 'childList') {
        const rootMaster = document.getElementById(
          'root-master',
        ) as HTMLElement;
        const newDom = targetNode?.childNodes[0]?.childNodes[0] as HTMLElement;
        if (newDom) {
          document.getElementById('watermark')?.remove();
          newDom.id = 'watermark';
          rootMaster.appendChild(newDom);
          observer.disconnect(); // 注销
        }
      }
    }
  };
  // 创建一个观察器实例并传入回调函数 MutationObserver的回调是微任务
  const observer = new MutationObserver(callback);
  // 以上述配置开始观察目标节点
  observer.observe(targetNode, config);
  // 方案二: 用动画帧刷新也可以(弃用)
  // const getFormRefLoop = () => {
  //   window.requestAnimationFrame(() => {
  //     const rootMaster = document.getElementById('root-master') as HTMLElement;
  //     const w = root?.childNodes[0]?.childNodes[0] as HTMLElement;
  //     if (rootMaster && w) {
  //       const old = document.getElementById('root');
  //       if (old) old.remove();
  //       w.id = 'root';
  //       rootMaster.appendChild(w);
  //     } else {
  //       getFormRefLoop();
  //     }
  //   });
  // };
  // getFormRefLoop();
};

export default creatWatermark;

小结

demo地址
原创不易,转载请注明来源. 如果对你有帮助,收藏关注加点赞哦😝 当然如果大家有更好的解决方案,欢迎评论哦

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
接入 umi3 和接入其他 React 应用一样,只需要在主应用中安装 `@umijs/plugin-qiankun` 插件,并在子应用中使用 `qiankun` 的 `registerMicroApps` 方法注册子应用。 具体步骤如下: 1. 在主应用中安装 `@umijs/plugin-qiankun` 插件: ```bash yarn add @umijs/plugin-qiankun -D ``` 2. 在主应用中的 `.umirc.ts` 或 `config/config.ts` 文件中配置 `qiankun` 插件: ```typescript export default { // ... plugins: ['@umijs/plugin-qiankun'], qiankun: { master: { // 主应用配置 }, }, }; ``` 3. 在主应用中使用 `qiankun` 的 `registerMicroApps` 方法注册子应用: ```typescript import { registerMicroApps, start } from 'qiankun'; import React from 'react'; import ReactDOM from 'react-dom'; function render({ appContent, loading }) { const container = document.getElementById('app-container'); ReactDOM.render( <div> {loading && <p>Loading...</p>} <div dangerouslySetInnerHTML={{ __html: appContent }} /> </div>, container, ); } registerMicroApps([ { name: 'sub-app', entry: '//localhost:8000', container: '#sub-app-container', activeRule: '/sub-app', }, ]); start(); ``` 4. 在子应用中使用 `react-app-rewired` 对 `create-react-app` 脚手架进行配置。 由于 `create-react-app` 脚手架默认隐藏了 webpack 配置,我们需要使用 `react-app-rewired` 来暴露 webpack 配置。具体做法可以参考官方文档:https://umijs.org/plugins/qiankun#%E5%AD%90%E5%BA%94%E7%94%A8 5. 在子应用中导出一个 render 方法,用于子应用启动时挂载到主应用中: ```typescript import React from 'react'; import ReactDOM from 'react-dom'; function render(props: any) { const { container } = props; ReactDOM.render(<App />, container); } export default render; ``` 6. 在子应用中使用 `qiankun` 的 `start` 方法启动子应用: ```typescript import { start } from 'qiankun'; import render from './render'; // 导出生命周期钩子函数 export const bootstrap = async () => {}; export const mount = async (props: any) => { render(props); }; export const unmount = async () => {}; // 启动子应用 start(); ``` 以上就是在 micro-app 前端中接入 umi3 react 的基本步骤,需要注意的是,在子应用中同样需要安装 `qiankun` 包和 `react` 包,并且在开发时需要同时启动主应用和子应用,才能看到前端的效果。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值