vue后台水印实现

vue后台水印实现

Vue项目在页面添加水印功能

创建watermark.js文件

<template>
    <router-view
        v-waterMark="waterCode"
    ></router-view>
</template>

<script>
import waterMark from 'common/utils/watermark';
export default {
    directives: {
        waterMark: waterMark,
    },
    computed: {
        waterCode() {
            return {text: `平台机密数据`,
                    style: {
                        'width': 700, // 单个水印的宽
                        'height': 300, // 单个水印的高
                        'font': 'normal 22px Microsoft Yahei', // 设置样式
                        'fillStyle': 'rgba(112, 113, 114, 0.1)', // 水印字体颜色
                        'rotate': (30 * Math.PI / 180), // 水印偏转角度
                    },
            };
        },
    },
};
</script>
/**
 * @file 网页水印
 */
/*eslint-disable*/
let watermark = {
    text: 'text',
    style: {},
    isAllowDele: false,
    maskDiv: '',
    init: (text) => {
        let canvas = document.createElement('canvas');
        canvas.id = 'canvas';
        canvas.width = watermark.style.width; // 单个水印的宽高
        canvas.height = watermark.style.height;
        watermark.maskDiv = document.createElement('div');
        let ctx = canvas.getContext('2d');
        ctx.font = watermark.style.font; // 设置样式
        ctx.fillStyle = watermark.style.fillStyle; // 水印字体颜色
        ctx.rotate(watermark.style.rotate); // 水印偏转角度
        // convas 设置换行
        CanvasRenderingContext2D.prototype.wrapText = function (text, x, y, maxWidth, lineHeight) {
            if (typeof text != 'string' || typeof x != 'number' || typeof y != 'number') {
                return;
            }
            var context = this;
            var canvas = context.canvas;
            if (typeof maxWidth == 'undefined') {
                maxWidth = (canvas && canvas.width) || watermark.style.width;
            }
            if (typeof lineHeight == 'undefined') {
                lineHeight = (canvas && parseInt(window.getComputedStyle(canvas).lineHeight)) || parseInt(window.getComputedStyle(document.body).lineHeight);
            }
            // 字符分隔为数组
            var arrText = text.split('');
            var line = '';
            for (var n = 0; n < arrText.length; n++) {
                var testLine = line + arrText[n];
                var metrics = context.measureText(testLine);
                var testWidth = metrics.width;
                if (testWidth > maxWidth && n > 0) {
                    context.fillText(line, x, y);
                    line = arrText[n];
                    y += lineHeight;
                } else {
                    line = testLine;
                }
            }
            context.fillText(line, x, y);
        };
        ctx.wrapText(watermark.text, 30, 20);
        let src = canvas.toDataURL('image/png');
        watermark.maskDiv.style.position = 'fixed';
        watermark.maskDiv.style.zIndex = '9999';
        watermark.maskDiv.id = '_waterMark';
        watermark.maskDiv.style.top = '60px';
        watermark.maskDiv.style.left = '0';
        watermark.maskDiv.style.height = '100%';
        watermark.maskDiv.style.width = '100%';
        watermark.maskDiv.style.pointerEvents = 'none';
        watermark.maskDiv.style.backgroundImage = 'URL(' + src + ')';
        // 水印节点插到body下
        document.body.appendChild(watermark.maskDiv);
    },
    // 防删机制
    monitor: () => {
        let body = document.getElementsByTagName('body')[0];
        let options = {
            childList: true,
            attributes: true,
            characterData: true,
            subtree: true,
            attributeOldValue: true,
            characterDataOldValue: true
        }
        let observer = new MutationObserver(watermark.callback);
        observer.observe(body, options); // 监听body节点
    },
    // DOM改变执行callback
    callback: (mutations, observer) => {
        // 当attribute属性被修改
        if (mutations[0].target.id === '_waterMark') {
            watermark.removeMaskDiv();
        }
        // 当id被改变时
        if (mutations[0].attributeName === 'id') {
            watermark.removeMaskDiv();
            watermark.init();
        }
        // 当节点被删除
        if (mutations[0].removedNodes[0] && mutations[0].removedNodes[0].id === '_waterMark') {
            watermark.init();
        }
    },
    /* public */
    // 手动销毁水印DOM
    removeMaskDiv: () => {
        document.body.removeChild(watermark.maskDiv);
    },
    render: () => {
        // let maskBox = document.querySelector('#_waterMark');
        if (!watermark.maskDiv) {
            watermark.init();
            // 是否允许通过js或开发者工具等途径修改水印DOM节点(水印的id,attribute属性,节点的删除),true为允许, 默认不允许
            if (!watermark.isAllowDele) {
                // 设置水印节点修改的DOM事件
                watermark.monitor();
            }
        }
    }
  }

  export default {
    bind(el, binding, vnode) {
        const options = binding.value;
        watermark.style =  options.style;
        watermark.text = options.text;
        watermark.isAllowDele = options.isAllowDele;
        watermark.render();
    },
    update(element, data) {
        if (data.value.text !== data.oldValue.text) {
            watermark.text = data.value.text;
            watermark.removeMaskDiv();
            watermark.render();
        }
    },
  };
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Vue后台管理系统的实现可以从以下几个方面进行描述: 首先,Vue是一种基于JavaScript的前端框架,借助于Vue的架构和组件化开发能力,我们可以快速搭建一个可靠、高效的后台管理系统。我们可以使用Vue的核心库来构建视图层,并结合Vue Router来实现前端路由的管理,使得页面之间的跳转更加流畅。 其次,后台管理系统往往需要与后端服务器进行数据交互,Vue提供了一个通过异步API与后端通信的方法,即Vue Resource或者Axios。我们可以使用这些工具来发送异步请求,并将获取到的数据渲染到视图中。 此外,Vue还提供了虚拟DOM的概念,通过对比虚拟DOM与真实DOM的差异,可以高效地更新页面,提高系统的性能。这对于复杂的后台管理系统来说,能够有效地提升用户体验。同时,Vue的响应式数据绑定也使得页面数据与视图保持同步,减少了手动操作的复杂性。 另外,为了提高开发效率,Vue还有丰富的插件生态系统,我们可以使用这些插件来扩展Vue的功能,实现某些特殊需求,比如数据表格、图表或是地图展示等。这些插件可以帮助我们更快速地完成系统的开发。 总结起来,Vue后台管理系统的实现主要借助于Vue的架构和组件化开发能力,结合Vue Router来管理前端路由,使用Vue Resource或者Axios与后端进行数据交互,利用虚拟DOM实现高效的页面更新,以及通过插件扩展实现特殊功能需求。这些特点使得Vue成为一个非常适合构建后台管理系统的前端框架。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值