为代码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);
}());
相关推荐
燃先生._.1 小时前
Day-03 Vue(生命周期、生命周期钩子八个函数、工程化开发和脚手架、组件化开发、根组件、局部注册和全局注册的步骤)
前端·javascript·vue.js
高山我梦口香糖2 小时前
[react]searchParams转普通对象
开发语言·前端·javascript
black^sugar3 小时前
纯前端实现更新检测
开发语言·前端·javascript
理想不理想v4 小时前
webpack最基础的配置
前端·webpack·node.js
2401_857600955 小时前
SSM 与 Vue 共筑电脑测评系统:精准洞察电脑世界
前端·javascript·vue.js
2401_857600955 小时前
数字时代的医疗挂号变革:SSM+Vue 系统设计与实现之道
前端·javascript·vue.js
GDAL5 小时前
vue入门教程:组件透传 Attributes
前端·javascript·vue.js
小白学大数据5 小时前
如何使用Selenium处理JavaScript动态加载的内容?
大数据·javascript·爬虫·selenium·测试工具
2402_857583495 小时前
基于 SSM 框架的 Vue 电脑测评系统:照亮电脑品质之路
前端·javascript·vue.js