软件教程 2025年08月6日
0 收藏 0 点赞 462 浏览 6092 个字
摘要 :

文章目录 序言 1. 需求分析 2. 实现步骤 2.1 仅添加水印情况 2.2 添加水印且要防篡改情况 3. 问题详解 3.1 关于MutationObserver总结 3.2 关于pointer-events的总结……




  • 序言
  • 1. 需求分析
  • 2. 实现步骤
    • 2.1 仅添加水印情况
    • 2.2 添加水印且要防篡改情况
  • 3. 问题详解
    • 3.1 关于MutationObserver总结
    • 3.2 关于pointer-events的总结

    本文主要讲解关于Vue3如何页面上添加水印 相关内容,让我们来一起学习下吧!

    序言

    本文主要内容分三部分,如果您只需要解决问题,请阅读第一、二部分即可。如果您有更多时间,进一步学习问题相关知识点,请阅读至第三部分。

    1. 需求分析

    为了防止网站信息被盗用,以及维护版权标识,常常需要在页面、图片或视频上添加独特水印,以作区分。

    同时,水印的添加不仅仅满足于添加,有时候还要能防止用户恶意篡改,时刻保证水印的功效。

    所以,这次问题我分为了两种情况:一种是仅添加水印仅可,另一种是添加水印且要防篡改。

    下面我将把实现一一列出。Vue3如何在页面上添加水印

    2. 实现步骤

    2.1 仅添加水印情况

    对于仅需要添加水印的情况,直接使用第三方UI库中的水印组件即可,简单快速。

    当然,我们也可以选择自己造轮子,用Canvas来画,但是对于工作而言,我觉得这样应该尽量避免。

    这里我使用ElementPlus 2.4.0中,新出的Watermark水印组件作为例子。

    实现代码:

    <template>
      <el-watermark
        :width=\"130\"
        :height=\"30\"
        image=\"https://element-plus.org/images/element-plus-logo.svg\"
      >
        <div style=\"height: 500px\" />
      </el-watermark>
    </template>
    

    效果如下:Vue3如何在页面上添加水印当然要注意的是,ElementPlus的依赖版本一定要是2.4.0之后的。

    2.2 添加水印且要防篡改情况

    像ElementPlus提供的水印组件,是不支持防篡改功能的。

    也就是说,如果有用户通过浏览器的控制台进行元素属性的修改,是可以把页面中的水印隐藏的。所以为了安全起见,是很需要做防篡改处理的。

    为了保证自定义水印的灵活性,这里我使用了原生js的写法,并且代码参考了渡一官方大佬的文章。

    简言之,就是利用Canvas绘制水印图像,以及利用MutationObserver对象来监听Dom节点或其子节点的变化以实现防篡改处理。

    代码实现如下:

    先写一个hook函数useWatermarkBg,在其中用Canvas绘制水印图像。

    import { computed } from \'vue\';
    export default function useWatermarkBg (props) {
      return computed(() => {
          // 创建一个 canvas
          const canvas = document.createElement(\'canvas\');
          const devicePixelRatio = window.devicePixelRatio || 1;
          // 设置字体大小
          const fontSize = props.fontSize * devicePixelRatio;
          const font = fontSize + \'px serif\';
          const ctx = canvas.getContext(\'2d\');
          // 获取文字宽度
          ctx.font = font;
          const { width } = ctx.measureText(props.text);
          const canvasSize = Math.max(100, width) + props.gap * devicePixelRatio;
          canvas.width = canvasSize;
          canvas.height = canvasSize;
          ctx.translate(canvas.width / 2, canvas.height / 2);
          // 旋转 45 度让文字变倾斜
          ctx.rotate((Math.PI / 180) * -45);
          ctx.fillStyle = \'rgba(0, 0, 0, 0.3)\';
          ctx.font = font;
          ctx.textAlign = \'center\';
          ctx.textBaseline = \'middle\';
          // 将文字画出来
          ctx.fillText(props.text, 0, 0);
          return {
              base64: canvas.toDataURL(),
              size: canvasSize,
              styleSize: canvasSize / devicePixelRatio,
          };
      });
    }
    

    再封装一个水印公共组件WaterMark,在其中调用useWatermarkBg函数生成水印图像,以及添加水印、做防篡改处理。

    mounted中,创建MutationObserver实例,监听水印DOM节点的变化,在节点删除或属性修改时设置依赖,发出重新添加水印的通知。

    watchEffect中,进行收集依赖,只要依赖变化了,它就会重新添加水印图像,达到防篡改效果。

    值得一提的是,因为添加水印的原理是给页面添加一个绝对定位的重复水印背景的div,但是,如果这样我们就不能点击div下层的元素了。

    所以,这里还用了一个叫pointerEvents的css属性,设置值为none,从而使元素不会接收鼠标事件,鼠标事件会透过元素传递到下层的元素上。

    <template>
      <div class=\"watermark-container\" ref=\"parentRef\">
        <slot></slot>
      </div>
    </template>
    
    <script setup>
    import { onMounted, onUnmounted, ref, watchEffect } from \'vue\';
    import useWatermarkBg from \'@/hooks/useWatermarkBg.js\';
    
    const props = defineProps({
      text: {
        type: String,
        required: true,
        default: \'watermark\',
      },
      fontSize: {
        type: Number,
        default: 40,
      },
      gap: {
        type: Number,
        default: 20,
      },
    });
    
    const bg = useWatermarkBg(props);
    const parentRef = ref(null);
    const flag = ref(0); // 声明一个依赖
    let div;
    
    watchEffect(() => {
      flag.value; // 将依赖放在 watchEffect 里
      if (!parentRef.value) {
        return;
      }
      if (div) {
        div.remove();
      }
      const { base64, styleSize } = bg.value;
    
      div = document.createElement(\'div\');
      div.style.backgroundImage = `url(${base64})`;
      div.style.backgroundSize = `${styleSize}px ${styleSize}px`;
      div.style.backgroundRepeat = \'repeat\';
      div.style.zIndex = 9999;
      div.style.position = \'absolute\';
      div.style.inset = 0;
      // 元素不会接收鼠标事件,鼠标事件会透过元素传递到下层的元素上
      div.style.pointerEvents = \'none\';
      parentRef.value.appendChild(div);
    });
    
    // 防篡改处理
    let ob;
    onMounted(() => {
      ob = new MutationObserver((records) => {
        for (const record of records) {
          for (const dom of record.removedNodes) {
            if (dom === div) {
              flag.value++; // 删除节点的时候更新依赖
              return;
            }
          }
          if (record.target === div) {
            flag.value++; // 修改属性的时候更新依赖
            return;
          }
        }
      });
      ob.observe(parentRef.value, {
        childList: true,
        attributes: true,
        subtree: true,
      });
    });
    
    onUnmounted(() => {
      ob && ob.disconnect();
      div = null;
    });
    </script>
    

    最后,在需要添加水印的页面直接使用即可。

    <template>
      <water-mark>
        <video src=\"@/assets/a.mp4\" controls width=\"500\" height=\"500\"></video>
      </water-mark>
    </template>
    
    <script setup>
    import WaterMark from \"@/components/WaterMark.vue\"
    </script>
    

    3. 问题详解

    3.1 关于MutationObserver总结

    MutationObserver 是 JavaScript 中的一个内置对象,它提供了一种监视 DOM(文档对象模型)树变化的能力。MutationObserver 允许开发者注册一个回调函数,当观察的 DOM 节点或子节点发生变化时,会触发这个回调函数。这些变化可以包括节点的添加、移除、属性的变化、文本内容的改变等。使用 MutationObserver 可以监视特定的 DOM 元素或整个文档,并在相关变化发生时执行相应的操作。这对于实时监测页面变化、自动化测试、实现响应式 UI 等场景非常有用。下面是一个简单的示例,演示如何使用 MutationObserver 监测某个元素的子节点变化:

    // 目标元素
    var targetElement = document.getElementById(\'target-element\');
    
    // 创建一个 MutationObserver 实例
    var observer = new MutationObserver(function(mutationsList, observer) {
      // 当变化发生时执行的回调函数
      for (var mutation of mutationsList) {
        if (mutation.type === \'childList\') {
          console.log(\'子节点发生变化\');
          console.log(mutation.addedNodes); // 添加的节点列表
          console.log(mutation.removedNodes); // 移除的节点列表
        }
      }
    });
    
    // 配置观察选项
    var config = { childList: true };
    
    // 开始观察目标元素
    observer.observe(targetElement, config);
    

    在上述示例中,我们首先通过 getElementById 获取目标元素,然后创建一个 MutationObserver 实例,传入一个回调函数作为参数。回调函数会在目标元素的子节点发生变化时被调用。我们可以在回调函数中根据 mutationsList 的内容进行相应的处理。在这个示例中,我们只关注子节点的变化,并打印相关信息到控制台。

    最后,我们通过调用 observe 方法来开始观察目标元素的变化。在 config 对象中,我们将 childList 属性设置为 true,表示我们要监测子节点的变化。

    需要注意的是,MutationObserver 是一个异步的机制,它会在变化发生后才触发回调函数。这意味着在开始观察之前的变化可能不会被捕获到。如果需要在开始观察之前立即获取当前状态的变化,可以在创建 MutationObserver 实例后,使用 observer.takeRecords() 方法来获取当前的变化记录。

    3.2 关于pointer-events的总结

    pointer-events 是一种 CSS 属性,它控制元素对鼠标事件的响应方式。它可以设置在任何 HTML 元素上,并具有以下几个可能的取值:

    • auto:元素对鼠标事件作出默认的响应。即元素会根据自身的样式和内容对鼠标事件做出适当的响应。
    • none:元素对鼠标事件不做出响应。即元素不会接收鼠标事件,鼠标事件会透过元素传递到下层的元素上。这相当于将元素变为不可点击,即使它位于页面上方或遮挡其他元素。
    • visiblePainted:元素对鼠标事件做出响应,但鼠标事件不会穿透元素,而是传递到下层的元素上。这意味着元素会接收鼠标事件,但不会阻止下层元素对鼠标事件的响应。
    • visibleFill:元素对鼠标事件做出响应,并会阻止鼠标事件传递到下层的元素上。这意味着元素会完全接收鼠标事件,并阻止下层元素对鼠标事件的响应。

    pointer-events 属性对于创建交互式的页面元素非常有用,可以控制元素是否能够接收和响应鼠标事件。通过将其设置为 none,可以使元素在外观上可见,但不会干扰下层元素的交互。

    需要注意的是,pointer-events 属性的兼容性有限,可能不支持所有浏览器或旧版本的浏览器。在使用时,建议先检查兼容性并提供备用方案或降级策略。

    以上就是关于Vue3如何在页面上添加水印相关的全部内容,希望对你有帮助。欢迎持续关注潘子夜个人博客(www.panziye.com),学习愉快哦!

微信扫一扫

支付宝扫一扫

版权: 转载请注明出处:https://www.zuozi.net/6636.html

管理员

相关推荐
2025-08-06

文章目录 一、Promise基础回顾 二、Promise 与 axios 结合使用场景及方法 (一)直接返回 axios …

269
2025-08-06

文章目录 一、模块初始化时的内部机制 二、常见导出写法的差异分析 (一)写法一:module.exports…

107
2025-08-06

文章目录 一、ResizeObserver详解 (一)ResizeObserver是什么 (二)ResizeObserver的基本用法 …

683
2025-08-06

文章目录 一、前期准备工作 (一)下载相关文件 (二)安装必要工具 二、处理扣子空间生成的文件…

338
2025-08-06

文章目录 一、官方文档 二、自动解包的数据类型 ref对象:无需.value即可访问 reactive对象:保持…

371
2025-08-06

文章目录 一、Hooks的工作原理 二、在if语句中使用Hook会出什么岔子? 三、React官方的Hook使用规…

843
发表评论
暂无评论

还没有评论呢,快来抢沙发~

助力内容变现

将您的收入提升到一个新的水平

点击联系客服

在线时间:08:00-23:00

客服QQ

122325244

客服电话

400-888-8888

客服邮箱

122325244@qq.com

扫描二维码

关注微信客服号