• 前端复制功能的若干 -- document.execCommand()


    最近涨停科技公司实习,由于backend基础太弱。。。强行前端了一把。。搞了两周才搞下页面里copy的功能,期间有些琐碎,恐忘,记录在此。

    目前copy主流有四种方式:ZeroClipboardClipboard.jsexecCommand,setData,再就是其他只支持IE的鸡肋法了不在此讨论。。

    概况:

      ZeroClipboard 就是常说的Flash法,通过加载一个Flash,让其访问系统剪贴板来绕过绝大多数系统的权限限制,然而体积稍微庞大些

      Clipboard.js 近几年使用较多,体积相对小,兼容性可以接受,使用还比较方便。

      execCommand 新兴势力,safari等主流正在努力兼容,是个好东西。

      setData 太老。。一般不太用,基本只适合IE

    兼容性:

      ZeroClipboard 兼容性最好,能全面兼容chrome/ FireFox/ IE/ 甚至Safari 这种“友好”的浏览器

      Clipboard.js和execCommand兼容性相似,兼容chrome/ FF/ IE>9/ Safari新版(不太懂Safari版本号如何算。。感觉15年以后的都可以)

      setData 仅IE

    体积:

      ZeroClipboard 插件较大,230KB

      Clipboard.js 较小,4KB

      execCommand是document方法,不用插件直接搞

    虽说体积有差,加载起来速度差不多的其实。。话说git好像就是用的ZeroClipboard

    Clipboard.js 实验经过:

      直接忽略胖胖的Flash法,,先盯上的Clipboard.js,用起来着实简单,先引用压缩版:

    <script src="dist/clipboard.min.js"></script>

    新建Clipboard对象(顺便:'.btn'给所有class="btn"的元素都加了监听,其他用法可查JS)

    var clipboard = new Clipboard('.btn');
    
    //可以自己加些处理
    clipboard.on('success', function(e) {
        console.info('Action:', e.action);
        console.info('Text:', e.text);
        console.info('Trigger:', e.trigger);
    
        e.clearSelection();
    });
    clipboard.on('error', function(e) {
        console.error('Action:', e.action);
        console.error('Trigger:', e.trigger);
    });

    HTML里这样就OK了

    <button class="btn" data-clipboard-target="#foo">

    使用清爽,测试通过,然而项目只有一个地方用到copy,为了他加个插件真是不优美。。于是终于找到了近期出现的execCommand()大法 (生在了好时代Orz)

    execCommand()大法:

      其实只需要选中要复制的内容,执行document.execCommand('copy', false, null)就好了。execCommand里可以跑很多例如paste等方法,第一个参数是方法名,第二个是是否展示默认ui,第三个是可选参数列表,对copy来说后两个都用不到。

      根据兼容不同,执行后可能的情况(涉及返回值):

        1.不支持execCommand:抛出异常          2.不支持copy方法:返回false                    3.成功:true

      因此框架可以这样写:

    copy_target.focus();
    copy_target.select();
    try{
        if(document.execCommand('copy', false, null)){
            //success info
        } else{
            //fail info
        }
    } catch(err){
        //fail info
    }

      给用户的反馈用的jquery的tooltip,然后写成一个function就是如下:

    function copy(copytargetid,copybtnid){
        var cpt = document.getElementById(copytargetid);
        var cpb = document.getElementById(copybtnid);
        $(cpt).focus();
        $(cpt).select();
        try{
            if(document.execCommand('copy', false, null)){
                $(cpb).tooltip({title:"copied!", placement: "bottom", trigger: "manual"});
                $(cpb).tooltip('show');
                cpb.onmouseout=function(){$(cpb).tooltip('destroy')};
            } else{
                $(cpb).tooltip({title:"failed!", placement: "bottom", trigger: "manual"});
                $(cpb).tooltip('show');
                cpb.onmouseout=function(){$(cpb).tooltip('destroy')};
            }
        } catch(err){
            $(cpb).tooltip({title:"failed!", placement: "bottom", trigger: "manual"});
            $(cpb).tooltip('show');
            cpb.onmouseout=function(){$(cpb).tooltip('destroy')};
        }
    }

    用的时候直接

    <button id="cpbtn" onclick="copy('cptar', 'cpbtn')">copy</button>

    即可

    到此还没有结束。。。

    项目用的vue,于是需要做成vue的method,又是用coffee写的,改了下语法,在初次渲染的html中测试通过了,然后。。。我的copy妞是个vex模态框。。button是写在vex.dialog.open的message里的,message是个字符串,弹窗时候强注一段html。而且vue函数是只在渲染阶段绑定,所以。。。初次vue渲染的时候不会识别到字符串中的v-on:click,无法绑定。。于是不能从button元素直接调。

    决定搞一个隐藏input中继一下,最后终于用比较优美的姿势实现了。。。(上次是直接在message里强行注入script。。。涉及script嵌套还加了个转义</script>,结果丑的一bi。。)

    button里 onclick="document.getElementById('copyrelay').select()",input里@select('copy(...)')(@是vue的v-on:的缩写)。

    终于测试一切完好,天真的以为加个display: none就大功告成。。结果发现跪了

    原来是display:none的元素并不能被select。。

    同样的,也不能focus, change等等,于是顺着onerror等事件挨个试了一遍。。发现貌似只有onclick work。。。

    另外还顺带试了一下,<input type="hidden"/>也是不能用那些事件;即使正常显示元素,value=""的话也不能触发select。

    当然,至于是.select()没有成功,还是元素没有触发select事件,还是没有触发v-on:select,有待确定,有时间可以试一下。

    Anyway,最终代码:

    <input id="copyrelay" style="display: none;" @click=“copy('cptg','cpbt')”/>
    
    <!--vex.dialog.open的message中:-->
    <input id="cpbt" type="button" onclick="document.getElementById('copyrelay').click()"/>
    <input id="cptg" value="copy test" readonly/>

    method中的copy函数如上所提,转为coffee。

    我这个伪frontend太弱了。。还是希望给贵司多搞点贡献。。。

    感谢lrx,lyy,P8,zzl,xxm犇们Orz。。。

    就这样。

  • 相关阅读:
    spring 注解笔记
    spring boot 拦截器
    spring boot 启动流程及其原理
    Spring之BeanFactory和FactoryBean接口的区别
    微信支付
    三级联动
    搜索分页
    多选标签
    分类界面 大分类小分类
    触底下拉
  • 原文地址:https://www.cnblogs.com/xhyu/p/5370111.html
Copyright © 2020-2023  润新知