需求:实现防止篡改的水印组件
注:该文章只探讨技术层面的实现 不考虑非技术手段
层面1:界面区域打上水印
层面2:防止篡改
<template>
<div class="container">
<Watermark text="版权所有">
<div class="content"></div>
</Watermark>
<Watermark text="禁止转载" style="background: #6400a0">
<div class="content"></div>
</Watermark>
</div>
</template>
<template>
<div class="water-container" ref="parentRef">
<slot></slot>
<!-- 此处新建一个div 把这个div做成一个防篡改的div-->
<div></div>
</div>
</template>
<script setup>
import useWatermarkBg from './useWatermarkBg';
const props = defineProps({
text:{
type:String,
required:true,
default:'watermark'
},
fontSize:{
type:Number,
default:40
},
gap:{
type:Number,
default:20
}
})
// 这个方法可以返回水印的base64 和尺寸
const bg = useWatermarkBg(props);
const parentRef = ref(null);
// 因为每次重新创建水印 都需要重新创建一个div 需要移除div
let div;
// 重置水印 -- 因为要防篡改
function resetWatermark(){
if(!parentRef.value) {
return;
}
if(div){
// parentRef.value.removeChild(div);
// 或
div.remove();
// 两种写法都可以
}
const {base64 , size} = bg.value;
div = document.createElement('div');
div.style.position = 'absolute';
div.style.backgroundImage = `url(${base64})`;
div.style.backgroundSize = `${size}px ${size}px`;
div.style.backgroundRepeat = `repeat`;
// 事件穿透 -- 点击水印不做任何处理
div.style.pointerEvents = 'none';
div.style.zIndex = 9999;
//背景图覆盖整个区域
div.style.inset = 0;
// 父元素如果有 就把元素加进去
parentRef.value.appendChild(div);
}
// 创建一个观察器
// 细节 : 到底应该观察什么元素, 只监控水印的div,别的div变化不做处理
const ob = new MutationObserver((entries)=>{
// 使用entries参数,把变化的东西都放在这个集合里
console.log('变化了')
for (const entry of entries){
// 关注两个属性
// removedNodes -- 表示这一次的变化是某一些节点被移除了 它会把被移除掉的节点放在这个集合里面
// target -- 表示是什么东西变化了 例:target:div.watermark-container
console.log('entry',entry)
// 处理被删除的情况
for (const node of entry.removedNodes) {
if(node === div){
// 如果相同就等于水印被删除了,那么就重置水印
resetWatermark();
return;
}
}
// 处理被修改的情况
console.log('entry',entry)
// 此时 removedNodes没有被修改 数组为0
// 被修改后 它的target就变了 变成了被修改的那个元素 例:target:div
// type:'attributes' 被修改的类型: 属性
// attributeName : 'style' 被修改的是什么属性 : style属性
if(entry.target === div){
// 如果要动水印那个元素 也需要重置一下
resetWatermark();
}
}
})
// 调用
// 1: 一开始调用
onMounted(()=>{
resetWatermark();
// 观察父元素
ob.observe(parentRef.value,{
// 观察父元素的子元素
childList : true,
// 观察子元素的子元素 子树
subtree : true,
// 观察属性的变化
attributes : true
})
})
// 2: 被篡改时调用 --- MutationObserver -> 被改动后的一个观察器
// 组件卸载后取消观察
onUnMounted(()=>{
ob.disconnect();
})
</script>
具体处理还有很多方法,上述只是在学习过程中发现的方法,如果有其他好用的方法,欢迎指教,上文只是参考总结