为代码pre code元素添加一件复制功能

Jаvascript

为代码块添加一个"复制代码"按钮,并实现点击按钮后将代码块的内容复制到剪贴板中。

  1. 首先通过document.querySelectorAll('pre')获取所有<pre>元素(即代码块)。
  2. 使用forEach方法遍历每个代码块。
  3. 创建一个文本元素 copyButton,设置其class为"copy",并将显示文本设置为"复制代码"。
  4. 创建一个容器元素 container,设置其class为"code-container",并将复制按钮添加到容器元素内。
  5. 将容器元素插入到代码块之前。
  6. 设置容器元素样式,使其定位为相对定位(position: relative)。
  7. 设置复制按钮样式,使其绝对定位于容器元素的右上角。
  8. 为复制按钮添加点击事件监听器。
  9. 在点击事件处理函数中,获取代码块的文本内容。
  10. if (navigator.clipboard && window.isSecureContext)以此判断使用不同的复制方法,使用navigator.clipboard.writeText(code).then(() => {}).catch(() => {});或采用document.execCommand('copy'); 这里需要借助创建textarea
  11. 创建一个临时的 <textarea> 元素,并将代码块的内容设置为其值。
  12. <textarea> 元素追加到 <body> 中。
  13. 选中 <textarea> 中的文本。
  14. 执行复制操作,将选中的文本复制到剪贴板中。
  15. 移除临时的 <textarea> 元素。
  16. 修改复制按钮文本为"复制成功"。

这段代码的作用是为网页中的代码块添加一个复制按钮,方便复制代码片段。

CSS

用于设置复制按钮和代码块的样式。具体样式如下:

  1. .code-wrapper 类选择器用于设置包裹代码块的容器元素的样式。在这里设置了相对定位(position: relative)。
  2. .code-block 类选择器用于设置代码块的样式。在这里设置了相对定位(position: relative)。
  3. .copy 类选择器用于设置复制按钮的样式。具体样式如下:
    • font-size:设置字体大小为 13px。
    • transition:设置颜色变化的过渡效果为 0.1秒。
    • color:设置按钮的颜色为带透明度的红色color: hsl(165.03deg 19.14% 92.37% / 97%);,背景为灰色background: #1b45bede;。
    • border:去掉按钮的边框。
    • border-radius:设置按钮的圆角为4px。
    • cursor:设置鼠标悬停在按钮上时的样式为指针。
    • z-index:将复制按钮的层级置于顶层,确保按钮显示在其他内容之上。

这些样式可以使用在前面提到的 jаvascript 脚本中的相关元素上,以实现更好的外观和交互效果。

js文件,直接在html中引用 ,如果是在vue中使用,需要在渲染html的方法中使用下面的js。

javascript 复制代码
(function () {
  "use strict"
  // 获取<pre>元素
  var codeBlocks = document.querySelectorAll('pre');
  var codeContainer = document.querySelectorAll(".code-container");
  if (codeBlocks && codeContainer.length === 0) {
    codeBlocks.forEach(function (codeBlock) {
      // 创建新的ol元素
      // const ol = document.createElement('ol');
      // // 获取所有<code>标签中的文本行
      // const codeLines = codeBlock.textContent.split('\n');
      // // 移除<pre>中的所有内容
      // codeBlock.innerHTML = '';
      // // 为每行代码添加序号并重新添加到<pre>中
      // codeLines.forEach((line, index) => {
      //     const lineNumber = index + 1;
      //     const lineElement = document.createElement('li');
      //     lineElement.textContent = `${line}`;//${lineNumber}. 
      //     ol.appendChild(lineElement);
      //     // codeBlock.innerHTML = `<ol><li>${codeBlock.innerHTML.replace(/\n/g,`</li><li class="line">`)}</li></ol>`;
      // });
      // codeBlock.appendChild(ol);

      var copyButton = document.createElement('span');
      copyButton.className = 'copy';
      copyButton.textContent = '复制代码';

      // 创建包裹代码块和按钮的容器元素
      var container = document.createElement('div');
      container.className = 'code-container';

      // 将按钮添加到容器元素内
      container.appendChild(copyButton);

      // 将容器元素插入到代码块之前
      codeBlock.parentNode.insertBefore(container, codeBlock);

      // 设置容器元素样式,使其定位为相对定位(position: relative)
      container.style.position = 'relative';

      // 设置复制按钮样式,使其绝对定位于容器元素的右上角
      copyButton.style.position = 'absolute';
      copyButton.style.top = '3px';
      copyButton.style.right = '6px';

      copyButton.addEventListener('click', function () {
        // 获取代码块的文本内容textContent
        var code = codeBlock.innerText;

        if (navigator.clipboard && window.isSecureContext) {
          try {
            navigator.clipboard.writeText(code).then(() => {
              // 修改复制按钮文本为"已复制"
              this.textContent = '复制成功';
            }).catch(() => {
              this.textContent = '复制失败';
            });
          } catch (err) {
            this.textContent = '复制失败';
          }
        } else {
          // 创建一个临时的textarea元素,并将代码块的内容设置为其值
          var textarea = document.createElement('textarea');
          textarea.value = code;
          // 将textarea元素追加到body中
          document.body.appendChild(textarea);
          // 选中textarea中的文本
          textarea.select();
          // 执行复制操作
          document.execCommand('copy');
          // 移除临时的textarea元素
          document.body.removeChild(textarea);
          this.textContent = '复制成功';
        }
        //一定时间后吧按钮名改回来
        setTimeout(() => {
          this.textContent = "复制代码";
        }, 1800);
      });
    });
  }

  if (document.getElementById("copy-code-styles")) return; // 避免重复添加样式
  const css = `
  .code-wrapper {
    position: relative;
  }

  .code-block {
    position: relative;
  }

  .copy {
    font-size: 13px;
    transition: color 0.1s;
    color: hsl(165.03deg 19.14% 92.37% / 97%);
    background: #1b45bede;
    padding: 0 3px;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    z-index: 1;
  }`;
  const style = document.createElement("style");
  style.id = "copy-code-styles";
  style.textContent = css;
  document.head.appendChild(style);
}());
相关推荐
别拿曾经看以后~37 分钟前
【el-form】记一例好用的el-input输入框回车调接口和el-button按钮防重点击
javascript·vue.js·elementui
川石课堂软件测试43 分钟前
性能测试|docker容器下搭建JMeter+Grafana+Influxdb监控可视化平台
运维·javascript·深度学习·jmeter·docker·容器·grafana
JerryXZR1 小时前
前端开发中ES6的技术细节二
前端·javascript·es6
problc1 小时前
Flutter中文字体设置指南:打造个性化的应用体验
android·javascript·flutter
Gavin_9151 小时前
【JavaScript】模块化开发
前端·javascript·vue.js
懒大王爱吃狼2 小时前
Python教程:python枚举类定义和使用
开发语言·前端·javascript·python·python基础·python编程·python书籍
待磨的钝刨3 小时前
【格式化查看JSON文件】coco的json文件内容都在一行如何按照json格式查看
开发语言·javascript·json
前端青山8 小时前
Node.js-增强 API 安全性和性能优化
开发语言·前端·javascript·性能优化·前端框架·node.js
从兄9 小时前
vue 使用docx-preview 预览替换文档内的特定变量
javascript·vue.js·ecmascript
清灵xmf11 小时前
在 Vue 中实现与优化轮询技术
前端·javascript·vue·轮询