请选择 进入手机版 | 继续访问电脑版

技术控

    今日:35| 主题:61447
收藏本版 (1)
最新软件应用技术尽在掌握

[其他] H5 的复制操作

[复制链接]
纠结_的男人 发表于 2016-11-27 22:39:54
193 0
一开始,在 Web 端,并没有任何可以接触到 clipborad 的内容。以前,我们想要执行 copy/paste/cut 只能借助 flash。但现在,伟大的 H5 又或者说 W3C 推出了关于 H5 操控 clipboard 的草案。最出名的就是两个 API:
  
       
  • document.execCommand()   
  • ClipboardEvent  
   我们一步一步来了解一下。先来看一下经典 execCommand 的使用。
  复制操作

  input 复制

  我们需要先了解一下,基本的复制过程:
  
       
  • 选中(select)   
  • 复制(command + c || ctrl + c)  
  实际效果就是:
   

H5 的复制操作

H5 的复制操作-1-技术控-command,flash,动态,经典,先来

   而,execCommand 也是遵循这一过程来实现这样的效果。如果我们想使用 execCommand 执行 copy 的话,那么应该先选中你想复制的元素。 这里,另外还会使用到一个新的 API, window.getSelection() 。具体来说就是:
  
       
  • getSelection(): 用来获得当前选中的元素的内容。一般而言就是用鼠标选中页面上的内容。
           
    • toString(): 用来将选中的内容直接变为 text 文本。   
       
  基本使用就是:
  1. // 输出选中的文本
  2. window.getSelection().toString();
复制代码
我们一般只是使用该 API 进行辅助作用。最常见的做法就是动态创建 input 元素,然后动态制定 input[value]。执行 select(), 进行选中,然后执行 copy 即可。
  1. # 总的代码就是
  2. function copyContent(elementId) {
  3.   // 动态创建 input 元素
  4.   var aux = document.createElement("input");
  5.   // 获得需要复制的内容
  6.   aux.setAttribute("value", document.getElementById(elementId).innerHTML);
  7.   // 添加到 DOM 元素中
  8.   document.body.appendChild(aux);
  9.   // 执行选中
  10.   // 注意: 只有 input 和 textarea 可以执行 select() 方法.
  11.   aux.select();
  12.   
  13.   // 获得选中的内容
  14.     var content = window.getSelection().toString();
  15.    
  16.   // 执行复制命令
  17.   document.execCommand("copy");
  18.   // 将 input 元素移除
  19.   document.body.removeChild(aux);
  20. }
复制代码
  看个实例
  任意复制

   当然,如果你想不动态添加 input 元素,想直接 copy 的指定 DOM 元素的话,应该怎么做呢?这里就需要使用到 HTML5 新提供的 createRange() 相关方法。当然,上面的 getSelection() 也是其中之一。用到的 API 有:
  
       
  • document.createRange(): 用来创建选中容器。返回一个 range Object。 该 API 的兼容性,也是挺好的, 手机端和 PC 端都支持 。
           
    • selectNode(DOM): 返回 range Object 上挂载的方法。用来添加选中元素。只能添加一个   
       
  • window.getSelection()
           
    • addRange(range): 这个方法是挂载到 getSelection() 方法下的,用来执行元素的选中。(!很重要)   
       
  上面 API 就这么一些:
   直接看 demo 吧
  这里,我贴一下关键代码:
  1. var copyDOM = document.querySelector('#selector');  
  2.   var range = document.createRange();  
  3.   // 选中需要复制的节点
  4.   range.selectNode(copyDOM);
  5.   // 执行选中元素
  6.   window.getSelection().addRange(range);
  7.   // 执行 copy 操作
  8. var successful = document.execCommand('copy');  
  9.   try {  
  10.     var msg = successful ? 'successful' : 'unsuccessful';  
  11.     console.log('copy is' + msg);  
  12.   } catch(err) {  
  13.     console.log('Oops, unable to copy');  
  14.   }
  15. // 移除选中的元素
  16.   window.getSelection().removeAllRanges();
复制代码
这里需要额外提醒一下,不能自动执行上述 copy 操作。即,在没有任何用户交互操作下,是不能执行 copy 等交互行为的。所以,这里需要用到 click 事件来辅助(当然,你也可以使用其他事件来进行代替)。
  使用 clipboard 复制

   首先, clipboard 是最近提出来的,所以它的兼容性还是需要等待时间去验证的, 目前的兼容性是支持一些简单的 event 。 如果,你的浏览器支持 ClipboardEvent Constructor 的话。那么 复制操作就变得异常简单。
  1. // 当然,下面的代码应该放在某个交互的 click 事件中。
  2. var copyEvent = new ClipboardEvent('copy', {
  3.             dataType: 'text/plain',
  4.             data: 'My string'
  5.         });
  6.         document.dispatchEvent(copyEvent);
复制代码
如果没有的话,就只能使用在 document 的 copy 事件中返回的 event.clipboardData API 来设置或者获取相关的信息。我们获得 clipboardData 对象只能通过事件回调来实现:
  
       
  • e.clipboardData: 只能通过 document 上的copy/paste/cut 事件来获取  
  1. document.addEventListener('copy', function(e){
  2.     // 设置信息,实现复制
  3.     e.clipboardData.setData('text/plain', 'Hello, world!');
  4.     e.preventDefault();
  5. });
复制代码

       
  • clipboardData: 该 obj 还挂载两个常用的 API
           
    • setData(format, data): 设置相关的数据信息,主要用于 copy 和 cut 的相关事件中。
              
      • format: 就是基本的 MIME type。最常用的就是 text/plain 。具体内容可以参考 MIME references      
      • data: 就是对应 MIME type 放入的具体数据内容      
            
    • getData(format): 一般用于 paste 事件中。用来获取 clipboard 里面的内容。不过,需要制定正确的解码格式(就是设置好正确的 MIME type)。并且,该方法只能在 paste 事件中使用。   
       
  上面感觉就是简单的介绍一下 API,接下来正式说一些干货。如果使用 clipboardData 实现自定义复制内容。这样,你不仅仅可以复制页面上简单的 text 文本,还可以复制图片信息等。
  看代码

  1. // 在指定 DOM 上绑定交互事件
  2. DOM.addEventListener('click',function(){},false){
  3.     // 添加 copy 内容
  4.     document.addEventListener('copy',function copy (e) {
  5.             msg = `<${msg}/>`;
  6.             e.clipboardData.setData('text/plain', msg);
  7.             e.preventDefault();
  8.         })
  9.     // 执行 copy 命令
  10.     document.execCommand('copy');
  11.     // 移除绑定事件
  12.     document.removeEventListener('copy','copy');
  13. }
复制代码
cut && paste 相关

   前面看起来也挺简单的。当然,有同学会想,不是还有其他事件比如 cut , paste 吗?是不是也可以这么做呢? 额… 一开始,我也是这么想的,但现实往往会给您一个轻轻的爱抚。因为,为了防止你恶意的获取用户信息,在 Chrome 中,一般而言你是不能通过 document.execCommand('paste') 触发 paste 事件。不过,在手机端中,规矩是,你可以在可编辑的元素中触发 cut 和 paste , 只能在有效的 选中 元素中,触发 copy。
  根据上面的说法,我们可以通过利用 paste 的相关方法,来具体应用到实践中。比如,防止用户粘贴信息。这特别适用于那些做题页面,防止你查资料然后 copy 相关答案。
  1. document.addEventListener('paste',function copy (e) {
  2.             e.preventDefault();
  3.         });
复制代码
  当然,还有更狠的,直接禁止 copy , paste , cut 事件。
  1. ['cut', 'copy', 'paste'].forEach((event)=>{
  2.     document.addEventListener(event, (e)=>{
  3.         e.preventDefault();
  4.     });
  5. });
复制代码
方案总结

   HTML5 现在能完美提供给我们的应该就是 copy 事件的使用,对于市面上的 clipboard.js 差不多也是运用上述的知识点。根据上面的描述,可以了解到,想要实现复制功能有三种渐进退化方案。以下兼容性由高到低:
  
       
  • input 模式   
  • createRange   
  • clipboard 直接操作  
   现在 React 比较火,这里我简单的写了一个 copybtn 组件 。具体的使用 README 已经写清楚了,如果有什么不懂的地方可以 @我。
我要投稿

推荐阅读


回页顶回复上一篇下一篇回列表
手机版/c.CoLaBug.com ( 粤ICP备05003221号 | 文网文[2010]257号 | 粤公网安备 44010402000842号 )

© 2001-2017 Comsenz Inc.

返回顶部 返回列表