js 实现代码模块粘贴复制功能

今天接受到需求,需要对之前做的代码高亮部分新增粘贴复制功能。

首先我们将复制按钮的dom结构与之前的pre code 的结构整合。

<div class="code-ct">    
  <div class="code-action">
    <div class="switch-btn">
      <i class="i-switch-1" title="明切暗"></i>
      <i class="i-switch-2" title="暗切明"></i>
    </div>
    <div class="copy-btn">
      <i class="i-copy" title="复制"></i>
      <div class="i-copy-txt" style="display: none;">复制成功</div>
    </div>
  </div>
  <pre>
    <code>
      代码内容XXX     </code>
  </pre>
</div>

 复制功能代码实现js如下

      r.on("click", ".i-copy", function(e) {
          var text = $(this).parents('.code-ct').children('pre').prevObject[0].innerText
          if (text.indexOf('复制成功') > 0) { // 处理IE 复制成功
            text = text.replace('复制成功','')
          }
          var textarea = document.createElement('textarea') //textarea
          textarea.value = text
          // document.body.appendChild(textarea) // ie会有滚到底部bug
          $(this).parents('.code-ct').append($(textarea))
          textarea.select(); // 选择对象
          document.execCommand("Copy"); // 执行浏览器复制命令
          textarea.className = 'copy-textarea'
          textarea.style.display='none'
         
          var a = parseInt($(this).data("timer")) || 0;
          var b = $(this).next();
          b.show(),
          a && clearTimeout(a),
          a = setTimeout(function() {
            b.hide()
            $('.copy-textarea').remove() // 删除textarea
          }, 1e3),
          $(this).data("timer", a)
        })

总结注意几点

1 功能实现核心方法 document.execCommand("Copy"); // 执行浏览器复制命令

2 网上有些创建input标签 document.createElement('input') 这样会导致代码格式丢失

3 插入新建deom方式 document.body.appendChild(textarea) 经测试在ie上会自动滚动到底部

  另还有弹框提示阻塞 textarea.style.display='none',通过样式影藏textarea标签。拷贝内容innerText含有标签内容,记得清除处理

4 创建后 将创建的临时dom删除 $('.copy-textarea').remove()

 ======= 上午高高兴兴提测后 下午bug就来了 说再苹果手机移动端无法复制 ========

解决方案  引入clipboard.js

<script src="/static/js/clipboard.js"></script>

添加影藏textarea

<textarea id="hide-texteare" v-show='false'></textarea>

对复制按钮绑定新属性data-clipboard-action的值是'copy '属性data-clipboard-target的值是textarea的id

<i class="i-copy" title="复制" data-clipboard-action="copy" data-clipboard-target="#hide-texteare"></i>   

js代码

        var clipboard = new ClipboardJS('.i-copy');
        clipboard.on('success', function(e) {
          var a = parseInt($(e.trigger).data("timer")) || 0;
          var b = $(e.trigger).next();
          b.show(),
          a && clearTimeout(a),
          a = setTimeout(function() {
            b.hide()
          }, 1e3),
          $(this).data("timer", a)
          e.clearSelection();
        });
        clipboard.on('error', function(e) {
          console.error('copy 失败');
        });

测试后 主流浏览器及移动端均可实现复制功能

 ============= bug 又来了 在ie上测试 发现动态数据无法复制完全 ===========================

为了解决该问题。自己决定将上述两种方式做兼容处理

      if (isIE()) {
          r.on("click", ".i-copy", function(e) {
            var text = $(this).parents('.code-ct').children('pre').prevObject[0].innerText
            if (text.indexOf('复制成功') > 0) { // 处理IE 复制成功
              text = text.replace('复制成功','')
            }
            // console.log('IE text========', text)
            var textarea = document.createElement('textarea') //textarea
            textarea.value = text
            // document.body.appendChild(textarea) // ie会有滚到底部bug
            $(this).parents('.code-ct').append($(textarea))
            textarea.select(); // 选择对象
            document.execCommand("Copy"); // 执行浏览器复制命令
            textarea.className = 'copy-textarea'
            textarea.style.display='none'
          
            var a = parseInt($(this).data("timer")) || 0;
            var b = $(this).next();
            b.show(),
            a && clearTimeout(a),
            a = setTimeout(function() {
              b.hide()
              $('.copy-textarea').remove() // 删除textarea
            }, 1e3),
            $(this).data("timer", a)
          })
        } else { // IE 使用ClipboardJS 动态数据复制不全
          r.on("click", ".i-copy", function(e) {
            var text = $(this).parents('.code-ct').children('pre').prevObject[0].innerText
            $("#hide-texteare").text(text)
            // console.log('非 IE text========', text)
          })
          var clipboard = new ClipboardJS('.i-copy');
          clipboard.on('success', function(e) {
            var a = parseInt($(e.trigger).data("timer")) || 0;
            var b = $(e.trigger).next();
            b.show(),
            a && clearTimeout(a),
            a = setTimeout(function() {
              b.hide()
            }, 1e3),
            $(this).data("timer", a)
            e.clearSelection();
          });
          clipboard.on('error', function(e) {
            console.error('copy 失败');
          });
        }
        
        function isIE() {
          if (!!window.ActiveXObject || "ActiveXObject" in window)
          return true;
          else
          return false;
        }

另外对修改了对clipboard.js全局引入方式,在webpack.base.conf.js中引入

resolve: {
    extensions: ['.js', '.vue', '.json'],
    alias: {
      'vue$': 'vue/dist/vue.esm.js',
      '@': resolve('src'),
      'api': path.resolve(__dirname, '../src/assets/api/index.js'),
      'assets': path.resolve(__dirname, '../src/assets'),
      'static': path.resolve(__dirname, '../static'),
      'ClipboardJS': 'clipboard/dist/clipboard.min.js'
    }
  },
plugins: [
  new webpack.optimize.CommonsChunkPlugin('common.js'),
  new webpack.ProvidePlugin({
      ClipboardJS: "ClipboardJS",
  })
  ]

  

 

posted @ 2019-03-13 14:43  cc_loving  阅读(1180)  评论(0编辑  收藏  举报