实现文章页代码行复制、粘贴功能
实现文章页代码行复制、粘贴功能

实现文章页代码行复制、粘贴功能

前情提要

虽然最近在学习服务器和SHELL的知识,浏览网页发现很多网页都有提供代码复制和粘贴的功能,而WordPress搭建的页面好像不能直接在页面中编辑<code></code>的统一样式,但是允许编辑单个code的HTML代码。

因此,我想要给自己的网站也实现这样的一个功能,随后通过智能Ai的生成以及自己的一些修改适配,获得了下面的完整代码:

<script>
document.addEventListener('DOMContentLoaded', function() {
    var preElements = document.querySelectorAll('pre');
    preElements.forEach(function(preElement) {
        var copyIconSpan = document.createElement('span');
        copyIconSpan.className = 'copy-icon';
        copyIconSpan.setAttribute('onclick', 'copyToClipboard(this)');
        copyIconSpan.style.position = 'absolute';
        copyIconSpan.style.right = '0em';
        copyIconSpan.style.top = '0em';
        
        var buttonElement = document.createElement('button');
        buttonElement.className = 'flex gap-1 items-center';
        buttonElement.style.padding = '5px';
        
        var svgElement = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
        svgElement.setAttribute('width', '24');
        svgElement.setAttribute('height', '24');
        svgElement.setAttribute('viewBox', '0 0 24 24');
        svgElement.setAttribute('fill', 'none');
        svgElement.className = 'icon-sm';
        
        var pathElement = document.createElementNS('http://www.w3.org/2000/svg', 'path');
        pathElement.setAttribute('fill-rule', 'evenodd');
        pathElement.setAttribute('clip-rule', 'evenodd');
        pathElement.setAttribute('d', 'M12 3.5C10.8954 3.5 10 4.39543 10 5.5H14C14 4.39543 13.1046 3.5 12 3.5ZM8.53513 3.5C9.22675 2.3044 10.5194 1.5 12 1.5C13.4806 1.5 14.7733 2.3044 15.4649 3.5H17.25C18.9069 3.5 20.25 4.84315 20.25 6.5V18.5C20.25 20.1569 19.1569 21.5 17.25 21.5H6.75C5.09315 21.5 3.75 20.1569 3.75 18.5V6.5C3.75 4.84315 5.09315 3.5 6.75 3.5H8.53513ZM8 5.5H6.75C6.19772 5.5 5.75 5.94772 5.75 6.5V18.5C5.75 19.0523 6.19772 19.5 6.75 19.5H17.25C18.0523 19.5 18.25 19.0523 18.25 18.5V6.5C18.25 5.94772 17.8023 5.5 17.25 5.5H16C16 6.60457 15.1046 7.5 14 7.5H10C8.89543 7.5 8 6.60457 8 5.5Z');
        pathElement.setAttribute('fill', 'currentColor');
        
        svgElement.appendChild(pathElement);
        buttonElement.appendChild(svgElement);
        copyIconSpan.appendChild(buttonElement);
        
        var checkMarkSpan = document.createElement('span');
        checkMarkSpan.className = 'check-mark';
        checkMarkSpan.innerHTML = '&#10003;';
        
        preElement.appendChild(copyIconSpan);
        preElement.appendChild(checkMarkSpan);
    });
});
  function copyToClipboard(button) {
      var buttons = document.querySelectorAll('.wp-block-code .copy-icon');
      for (var i = 0; i < buttons.length; i++) {
        if (buttons[i] === button) {
          var codeText = document.querySelectorAll('.wp-block-code code')[i].innerText;
          navigator.clipboard.writeText(codeText).then(function () {
            showCheckMark(button,i);
            setTimeout(function () {
              hideCheckMark(button,i);
            }, 2000); // 2秒后隐藏对勾提示
          }, function (err) {
            console.error('Failed to copy: ', err);
          });
          break;
        }
      }
    }

    function showCheckMark(button,num) {
      button.style.display = 'none';
      var checkMark = document.querySelectorAll('.check-mark')[num];
      checkMark.style.display = 'inline';
    }

    function hideCheckMark(button,num) {
      button.style.display = 'block';
      var checkMark = document.querySelectorAll('.check-mark')[num];
      checkMark.style.display = 'none';
    }
</script>
<style>
    .wp-block-code {
      position: relative;
    }

    .wp-block-code .copy-icon {
      position: absolute;
      top: 0;
      right: 0;
      cursor: pointer;
    }

    .check-mark {
      position: absolute;
      font-size: 50px;
      top: -0.5em;
      right: 0em;
      display: none;
      color: green;
    }
  </style>

将这个代码实施到WordPress平台的外观-主体文件编辑器、文章页面(single.php)内。

未实现代码的复制、粘贴功能前:

实现代码的复制、粘贴功能后:

编写这篇文章的意图主要有两个,一是分享自己的这个代码,其他人都可以直接复制到自己WordPress中进行使用,第二个是想要分析一下这个代码的含义。因为工作变动等原因,好久没有接触js了,虽然给我这个代码,我能改,但是要我写,我写不出来。

因此,这也算是一次复习知识,下面我们将在Ai的带领下,重温每一个js代码的知识点。

配置环境

1、CMS:WordPress 6.5.2版本

2、WordPress主题:Bravada 1.1.1版本

实现思路

前面,我们已经提到了想要实现的效果是给代码行,提供一个复制、粘贴的功能。

我们可以查看原生的页面代码,会发现代码的展示样式为:

<pre class="wp-block-code">
	<code>cp ~/.ssh/id_rsa{,backup} 
	cp ~/.ssh/id_rsa.pub{,backup}</code>
</pre>

因此,我们需要给每一个代码段都添加两个按钮,一个复制按钮,一个复制成功的反馈提示。然后,我们通过js来实现每一个复制按钮的复制内容。

那么,如何来实现点击复制按钮,就可以复制对应的code内容呢?

最好的思路就是遍历,简单的说,就是通过js来检索每一个代码行,然后我们在每一个pre代码段的底部插入两个按钮,然后在点击按钮时,通过遍历来查看点击的按钮是第几个。

比如,我们文章页中有12个代码段,我们在12个代码段中都插入了两个按钮,然后在点击第6个代码段的复制按钮时,会执行一个遍历的代码,判断点击的按钮是第几个。执行后,代码是识别出点击的是第6个复制按钮,然后我们再通过遍历,把第6个代码段中的<code></code>内容复制出来即可。

最后还有一个补充效果,就是按钮复制按钮后,复制按钮小时,显示复制成功的反馈,等待2秒后,隐藏复制成功反馈并恢复复制按钮。

代码解析

好了,思路我们有了,接着开始解析上面的完整代码:

1、在每个pre代码段中插入两个按钮

document.addEventListener('DOMContentLoaded', function() {
    var preElements = document.querySelectorAll('pre');
    preElements.forEach(function(preElement) {
        var copyIconSpan = document.createElement('span');
        copyIconSpan.className = 'copy-icon';
        copyIconSpan.setAttribute('onclick', 'copyToClipboard(this)');
        copyIconSpan.style.position = 'absolute';
        copyIconSpan.style.right = '0em';
        copyIconSpan.style.top = '0em';
        
        var buttonElement = document.createElement('button');
        buttonElement.className = 'flex gap-1 items-center';
        buttonElement.style.padding = '5px';
        
        var svgElement = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
        svgElement.setAttribute('width', '24');
        svgElement.setAttribute('height', '24');
        svgElement.setAttribute('viewBox', '0 0 24 24');
        svgElement.setAttribute('fill', 'none');
        svgElement.className = 'icon-sm';
        
        var pathElement = document.createElementNS('http://www.w3.org/2000/svg', 'path');
        pathElement.setAttribute('fill-rule', 'evenodd');
        pathElement.setAttribute('clip-rule', 'evenodd');
        pathElement.setAttribute('d', 'M12 3.5C10.8954 3.5 10 4.39543 10 5.5H14C14 4.39543 13.1046 3.5 12 3.5ZM8.53513 3.5C9.22675 2.3044 10.5194 1.5 12 1.5C13.4806 1.5 14.7733 2.3044 15.4649 3.5H17.25C18.9069 3.5 20.25 4.84315 20.25 6.5V18.5C20.25 20.1569 19.1569 21.5 17.25 21.5H6.75C5.09315 21.5 3.75 20.1569 3.75 18.5V6.5C3.75 4.84315 5.09315 3.5 6.75 3.5H8.53513ZM8 5.5H6.75C6.19772 5.5 5.75 5.94772 5.75 6.5V18.5C5.75 19.0523 6.19772 19.5 6.75 19.5H17.25C18.0523 19.5 18.25 19.0523 18.25 18.5V6.5C18.25 5.94772 17.8023 5.5 17.25 5.5H16C16 6.60457 15.1046 7.5 14 7.5H10C8.89543 7.5 8 6.60457 8 5.5Z');
        pathElement.setAttribute('fill', 'currentColor');
        
        svgElement.appendChild(pathElement);
        buttonElement.appendChild(svgElement);
        copyIconSpan.appendChild(buttonElement);
        
        var checkMarkSpan = document.createElement('span');
        checkMarkSpan.className = 'check-mark';
        checkMarkSpan.innerHTML = '&#10003;';
        
        preElement.appendChild(copyIconSpan);
        preElement.appendChild(checkMarkSpan);
    });
});

1、DOMContentLoaded 事件:

document.addEventListener('DOMContentLoaded', function() {});

DOMContentLoaded 事件在 HTML 文档加载完毕并且 DOM 树构建完成后触发。这意味着当浏览器已经完全加载 HTML 页面,并且所有的 DOM 元素都已经创建好,但是图片和其他资源可能尚未加载完成时,DOMContentLoaded 事件会被触发。

在 JavaScript 中,使用 document.addEventListener(‘DOMContentLoaded’, function() {}) 来监听 DOMContentLoaded 事件。这段代码告诉浏览器,当 HTML 文档的 DOM 内容加载完毕后执行指定的函数。在这个函数内部,可以执行需要在页面加载完成后立即进行的操作,比如修改 DOM 元素、添加事件监听器等。

例如,如果想在页面加载后执行某些 JavaScript 操作,可以将这些操作放置在 DOMContentLoaded 事件监听器内部,确保这些操作不会影响页面的加载速度和性能。

DOM:DOM(文档对象模型)是一种编程接口,它将 HTML、XML 和 XHTML 文档表示为树状结构,并允许开发者使用编程语言(如 JavaScript)来操作这些文档。DOM 将文档中的每个元素、属性、文本节点等都视为对象,并提供了一组方法和属性,用于访问、修改和操作这些对象。

DOM 将整个文档表示为一个树状结构,树的根节点称为文档节点(Document Node),其余节点包括元素节点(Element Node)、属性节点(Attribute Node)、文本节点(Text Node)等。开发者可以通过 DOM 提供的方法和属性来遍历和操作文档树中的各个节点,从而实现对文档内容的动态控制和交互。

使用 DOM,开发者可以轻松地通过编程方式操作网页的内容和结构,例如添加、删除或修改元素、样式和事件等。这使得 JavaScript 能够与 HTML 页面进行更加灵活和动态的交互,从而实现丰富的用户体验和功能。

2、遍历<pre>元素

var preElements = document.querySelectorAll('pre');

这行代码是使用 JavaScript 中的 document.querySelectorAll() 方法来查找文档中所有的 <pre> 元素,并将它们保存在一个变量 preElements 中。

具体解释如下:

  • document 表示当前 HTML 文档的对象,是 JavaScript 中用来访问文档的入口点。
  • querySelectorAll(‘pre’)document 对象的一个方法,它接收一个 CSS 选择器作为参数,用于查找文档中匹配该选择器的所有元素。在这里,选择器 ‘pre’ 表示选择所有的 <pre> 元素。
  • preElements 是一个变量名,用于存储查找到的所有 <pre> 元素。

因此,这行代码的作用是查找 HTML 文档中所有的 <pre> 元素,并将它们保存在 preElements 变量中,以便后续对它们进行操作。

3、遍历处理<pre>元素

preElements.forEach(function(preElement) {})

这行代码使用了 JavaScript 中的 forEach() 方法,对存储在 preElements 变量中的所有 <pre> 元素进行迭代处理。

具体解释如下:

  • preElements 是一个类数组对象,其中存储了所有匹配到的 <pre> 元素。
  • forEach() 是 JavaScript 数组对象的一个方法,用于遍历数组中的每个元素,并对每个元素执行指定的函数。
  • 在这行代码中,forEach() 方法接受一个函数作为参数,该函数定义了对每个 <pre> 元素执行的操作。函数的参数 preElement 表示当前被迭代处理的 <pre> 元素。

forEach()方法:forEach() 方法中,preElement 是一个参数名,它表示当前正在被处理的数组元素。在这种情况下,forEach() 方法是在 preElements 变量上调用的,因此 preElement 代表了 preElements 数组中的每个元素,即每个 <pre> 元素。

在 JavaScript 中,forEach() 方法的工作原理是对数组中的每个元素执行一次指定的函数,并将当前正在处理的元素作为参数传递给该函数。在这里,forEach() 方法会将 preElements 数组中的每个 <pre> 元素依次传递给处理函数,并在函数内部以 preElement 参数的形式访问和操作这些元素。

4、设置元素属性、事件、样式

var copyIconSpan = document.createElement('span');
        copyIconSpan.className = 'copy-icon';
        copyIconSpan.setAttribute('onclick', 'copyToClipboard(this)');
        copyIconSpan.style.position = 'absolute';
        copyIconSpan.style.right = '0em';
        copyIconSpan.style.top = '0em';

这段代码创建了一个新的 <span> 元素,并设置了它的类名、点击事件、自定义属性以及样式。

具体解释如下:

  • document.createElement(‘span’) 创建了一个新的 <span> 元素。
  • copyIconSpan.className = ‘copy-icon’; 将该 <span> 元素的类名设置为 ‘copy-icon’,这通常用于指定元素的样式。
  • copyIconSpan.setAttribute(‘onclick’, ‘copyToClipboard(this)’); 将一个点击事件的处理函数 copyToClipboard(this) 添加到该 <span> 元素上。当用户点击该元素时,会调用名为 copyToClipboard 的函数,并将当前元素自身作为参数传递给该函数。
  • copyIconSpan.style.position = ‘absolute’; 将该 <span> 元素的 CSS 定位属性设置为 ‘absolute’,这意味着该元素将相对于其最近的已定位祖先元素进行定位。
  • copyIconSpan.style.right = ‘0em’; 将该 <span> 元素的 CSS 右边距属性设置为 ‘0em’,将其右边距设置为相对于其包含块(通常是 <pre> 元素)右边缘的 0em 的距离。
  • copyIconSpan.style.top = ‘0em’; 将该 <span> 元素的 CSS 顶边距属性设置为 ‘0em’,将其顶边距设置为相对于其包含块(通常是 <pre> 元素)顶边缘的 0em 的距离。

这段代码主要用于创建一个具有特定样式和行为的 <span> 元素,通常用作复制按钮的图标。

5、将设置的元素追加到父元素中

svgElement.appendChild(pathElement);
buttonElement.appendChild(svgElement);
copyIconSpan.appendChild(buttonElement);

这段代码用于将创建的 SVG 路径元素和按钮元素添加到指定的父元素中。

具体解释如下:

  • svgElement.appendChild(pathElement); 将创建的路径元素 pathElement 添加为 SVG 元素 svgElement 的子元素。这个路径元素通常代表了某个图标或图形的形状。
  • buttonElement.appendChild(svgElement); 将创建的 SVG 元素 svgElement 添加为按钮元素 buttonElement 的子元素。这个按钮元素可能是一个 <button> 元素,用于实现点击功能。
  • copyIconSpan.appendChild(buttonElement); 将创建的按钮元素 buttonElement 添加为 <span> 元素 copyIconSpan 的子元素。这个 <span> 元素通常是用来包裹按钮和图标的容器,以便于在页面布局中进行定位和样式控制。

通过这些操作,可以将创建的 SVG 图标元素和按钮元素嵌套到指定的父元素中,从而实现对复制按钮的完整构建和定位。

appendChild() 是 JavaScript 中用于将一个元素(节点)添加为另一个元素(节点)的子元素的方法。

具体解释如下:

  • parentNode.appendChild(newNode) 方法将 newNode 添加为 parentNode 的子节点。其中,parentNode 是现有的父节点,而 newNode 则是要添加的新子节点。
  • 当调用 appendChild() 方法时,newNode 将被添加到 parentNode 的子节点列表的末尾。如果 newNode 已经存在于文档中的其他位置,它将首先从原来的位置删除,然后再被添加到新的位置。

在上述代码片段中,appendChild() 方法被用于将创建的 pathElementsvgElementbuttonElement 分别添加到它们各自的父元素中,以构建复制按钮的结构。

6、设置复制成功按钮

checkMarkSpan.innerHTML = '&#10003;';

这行代码将字符串 ‘&#10003;’(HTML 实体编码表示的对勾符号 ✓)作为 HTML 内容设置到 checkMarkSpan 元素中。

具体解释如下:

  • innerHTML 是一个 DOM 元素的属性,用于获取或设置元素的 HTML 内容。
  • checkMarkSpan.innerHTML = ‘&#10003;’; 这行代码将 HTML 实体编码 &#10003; 表示的对勾符号设置为 checkMarkSpan 元素的 HTML 内容。

因此,这行代码的作用是在页面中的某个元素 checkMarkSpan 中显示一个对勾符号 ✓。

2、设置插入按钮的js效果

function copyToClipboard(button) {
      var buttons = document.querySelectorAll('.wp-block-code .copy-icon');
      for (var i = 0; i < buttons.length; i++) {
        if (buttons[i] === button) {
          var codeText = document.querySelectorAll('.wp-block-code code')[i].innerText;
          navigator.clipboard.writeText(codeText).then(function () {
            showCheckMark(button,i);
            setTimeout(function () {
              hideCheckMark(button,i);
            }, 2000); // 2秒后隐藏对勾提示
          }, function (err) {
            console.error('Failed to copy: ', err);
          });
          break;
        }
      }
    }

1、获取全部的复制按钮

var buttons = document.querySelectorAll('.wp-block-code .copy-icon');

这行代码使用 CSS 选择器 .wp-block-code .copy-icon 来查找文档中所有具有类名 .copy-icon 的元素,且这些元素是 .wp-block-code 元素的后代。

具体解释如下:

  • document.querySelectorAll(‘.wp-block-code .copy-icon’) 使用 querySelectorAll() 方法来查找文档中所有符合指定 CSS 选择器的元素。
  • CSS 选择器 .wp-block-code .copy-icon 表示选取所有类名为 .copy-icon 的元素,并且这些元素是类名为 .wp-block-code 的元素的后代(即嵌套在 .wp-block-code 元素内部)。
  • 结果将返回一个 NodeList 对象,其中包含了所有匹配到的元素。

因此,这行代码的作用是获取文档中所有在 .wp-block-code 元素内部,并具有类名 .copy-icon 的元素,通常这些元素是用作复制按钮的图标。

2、遍历全部的复制按钮

for (var i = 0; i < buttons.length; i++) {}

这段代码是一个经典的 for 循环,用于遍历存储在变量 buttons 中的元素列表。

具体解释如下:

  • for 循环用于迭代执行一个代码块,可以指定起始条件、终止条件和每次迭代之后的操作。
  • var i = 0; 在循环开始前初始化一个计数器变量 i,并将其初始值设置为 0。
  • i < buttons.length; 设置了循环的终止条件,即当计数器变量 i 的值小于 buttons 数组的长度时,继续执行循环。
  • i++ 是每次迭代结束后执行的操作,它将计数器变量 i 的值递增 1,以便在下一次迭代时访问下一个元素。
  • 循环体中的代码会在每次迭代中执行,其中可以使用计数器变量 i 来访问当前正在处理的元素,即 buttons[i]

3、判断点击的按钮为遍历中的第几个

if (buttons[i] === button) {}

这段代码用于检查在循环中当前迭代的 buttons 数组中的元素是否与特定的 button 元素相匹配。

具体解释如下:

  • buttons[i] 表示 buttons 数组中当前迭代的元素。
  • === 是 JavaScript 中的严格相等运算符,用于比较两个值是否严格相等,包括值和类型。
  • button 是一个特定的元素,可能是在前面的代码中创建的某个按钮元素。

4、获取第i个code内容

var codeText = document.querySelectorAll('.wp-block-code code')[i].innerText;

这行代码用于获取指定索引 i 处的 .wp-block-code code 元素的文本内容。

具体解释如下:

  • document.querySelectorAll(‘.wp-block-code code’) 会返回所有匹配 CSS 选择器 .wp-block-code code 的元素的列表。
  • [i] 使用索引 i 来获取列表中的第 i 个元素。
  • .innerText 是获取元素的文本内容的属性。

因此,这行代码的作用是获取指定索引处的 .wp-block-code code 元素的文本内容,并将其存储在变量 codeText 中。通常这个元素包含代码块的文本内容。

5、将内容复制到剪切板

navigator.clipboard.writeText(codeText).then(function () {
    showCheckMark(button,i);
    setTimeout(function () {
      hideCheckMark(button,i);
    }, 2000); // 2秒后隐藏对勾提示
  }, function (err) {
    console.error('Failed to copy: ', err);
  });
  break;

这段代码是一个异步操作,用于将文本内容 codeText 复制到剪贴板,并在复制成功后显示一个对勾提示,然后在2秒后隐藏该提示。

具体解释如下:

  • navigator.clipboard.writeText(codeText) 是一个异步操作,用于将指定的文本内容 codeText 复制到剪贴板中。
  • .then() 方法用于在异步操作成功完成后执行一个回调函数。在这里,当文本复制操作成功完成时,会调用一个匿名函数,其中包含了显示对勾提示和设置定时器隐藏提示的操作。
  • showCheckMark(button,i) 是显示对勾提示的函数,它接受两个参数:按钮元素 button 和索引 i
  • setTimeout() 函数用于在指定的延迟时间后执行一个操作。在这里,设置了一个2秒的延迟时间,然后在回调函数中调用 hideCheckMark() 函数,用于隐藏对勾提示。
  • hideCheckMark(button,i) 是隐藏对勾提示的函数,它接受两个参数:按钮元素 button 和索引 i
  • break; 语句用于结束当前的循环,通常用于在 for 循环或 switch 语句中提前退出循环。

因此,这段代码的作用是在复制文本到剪贴板成功后,显示一个对勾提示,并在2秒后隐藏该提示。

navigator.clipboard.writeText(codeText)

navigator.clipboard.writeText(codeText) 是一个 JavaScript API,用于将指定的文本内容 codeText 复制到剪贴板中。

具体解释如下:

  • navigator.clipboard 是一个表示系统剪贴板的对象,通过它可以进行剪贴板操作。
  • .writeText(codeText)navigator.clipboard 对象的方法,用于将文本内容 codeText 写入剪贴板。
  • 当调用这个方法时,浏览器会尝试将指定的文本内容写入到用户的剪贴板中。这个操作通常是异步的,因此可以使用 .then() 方法来处理成功或失败的情况。

因此,navigator.clipboard.writeText(codeText) 的作用是将指定的文本内容复制到用户的剪贴板中。

navigator.clipboard

navigator.clipboard 是 Web API 的一部分,用于与剪贴板进行交互。它是 navigator 对象的一个属性,提供了一组方法,允许 JavaScript 代码读取和写入剪贴板内容。

具体来说,navigator.clipboard 对象包含以下主要方法:

  • writeText(text):将指定的文本写入剪贴板。
  • readText():从剪贴板中读取文本内容。

这些方法通常用于实现网页中的复制和粘贴功能,以及与剪贴板相关的其他操作。需要注意的是,对剪贴板的访问通常受到浏览器的安全策略限制,并且某些方法可能需要用户的授权才能执行。

navigator

navigator 是一个全局对象,代表了浏览器的状态和身份信息。它提供了许多属性和方法,用于获取关于浏览器和用户环境的信息,以及执行与浏览器相关的操作。

具体来说,navigator 对象提供了诸如以下功能:

  • 获取用户的语言和地区设置。
  • 获取用户的浏览器名称和版本号。
  • 获取用户的操作系统信息。
  • 获取设备的屏幕分辨率和像素密度。
  • 与剪贴板进行交互。
  • 等等。

在前端开发中,navigator 对象经常用于检测浏览器特性、优化用户体验以及执行与浏览器环境相关的操作。

then(function () {}, function (err) {});

then() 是 Promise 对象的方法,用于指定 Promise 对象状态变更时的回调函数。

具体来说,then() 方法接受两个参数:

  • 第一个参数是在 Promise 对象状态变为 fulfilled(已解决)时执行的回调函数。
  • 第二个参数是在 Promise 对象状态变为 rejected(已拒绝)时执行的回调函数。

通常情况下,我们可以通过链式调用 then() 方法来处理异步操作的结果。当 Promise 对象状态变为 fulfilled 时,会调用第一个参数指定的回调函数;当 Promise 对象状态变为 rejected 时,会调用第二个参数指定的回调函数。

示例:

promise.then(
    function(result) {
      // 处理 Promise 对象状态变为 fulfilled 的情况
      console.log('Promise 已解决,结果为:', result);
    },
    function(error) {
      // 处理 Promise 对象状态变为 rejected 的情况
      console.error('Promise 已拒绝,错误为:', error);
    }
  );

then() 方法中,通常会处理异步操作的成功和失败情况,以便在这些情况下执行相应的逻辑操作。

Promise

Promise 是 JavaScript 中的一个内置对象,用于处理异步操作。

在 JavaScript 中,通常会遇到一些需要等待一段时间才能得到结果的操作,比如从服务器获取数据、读取文件等。这些操作是异步的,不会阻塞代码的执行。Promise 提供了一种处理异步操作的方式,它表示一个异步操作的最终完成(或失败)及其结果的值。

一个 Promise 可以处于以下三种状态之一:

  1. Pending(进行中):初始状态,即操作尚未完成或失败。
  2. Fulfilled(已成功):操作成功完成。
  3. Rejected(已拒绝):操作失败。

Promise 对象有以下两个重要的特点:

  • 状态不受外界影响:Promise 的状态一旦改变,就不会再变,任何时候都可以得到这个结果。
  • 状态改变后不会再变化:一旦状态变为 FulfilledRejectedPromise 对象的状态和值就会固定下来,不会再改变。

Promise 对象具有一个 then() 方法,用于在异步操作成功或失败时执行相应的回调函数。then() 方法接受两个参数:一个是处理成功情况的回调函数,另一个是处理失败情况的回调函数。

示例:

const myPromise = new Promise(function(resolve, reject) {
    // 异步操作,比如从服务器获取数据
    // 如果操作成功,调用 resolve() 并传递结果
    // 如果操作失败,调用 reject() 并传递错误信息
  });
  
  myPromise.then(
    function(result) {
      // 处理异步操作成功的情况
      console.log('操作成功,结果为:', result);
    },
    function(error) {
      // 处理异步操作失败的情况
      console.error('操作失败,错误为:', error);
    }
  );

这是 Promise 的基本使用方法,它使得异步操作的处理变得更加清晰和可控。

3、设置按钮的切换效果

function showCheckMark(button,num) {
      button.style.display = 'none';
      var checkMark = document.querySelectorAll('.check-mark')[num];
      checkMark.style.display = 'inline';
}

function hideCheckMark(button,num) {
      button.style.display = 'block';
      var checkMark = document.querySelectorAll('.check-mark')[num];
      checkMark.style.display = 'none';
}

这两个函数分别用于显示和隐藏对勾提示(check mark)。

函数 showCheckMark(button, num)

  • 接受两个参数:
    • button:需要隐藏的按钮元素。
    • num:对勾提示的索引,用于选择要显示的对勾提示元素。
  • 首先,将按钮的 display 样式设置为 none,使按钮隐藏。
  • 然后,通过查询所有具有类名 .check-mark 的元素,选择索引为 num 的元素,并将其 display 样式设置为 inline,以显示对勾提示。

函数 hideCheckMark(button, num)

  • showCheckMark() 函数类似,也接受两个参数,分别是需要显示的按钮元素和对勾提示的索引。
  • 首先,将按钮的 display 样式设置为 block,以确保按钮显示。
  • 然后,通过查询所有具有类名 .check-mark 的元素,选择索引为 num 的元素,并将其 display 样式设置为 none,以隐藏对勾提示。

这两个函数通常用于控制显示和隐藏对勾提示的过程。通过调用这两个函数,可以在页面中控制对勾提示的显示和隐藏状态。

最后总结

根据上面的代码,依次可以了解到对应的效果以及其实现机制。

最后说一点题外话,目前通过Ai来编写代码的质量和速度都有很高的效率,最近呢,也看了一些关于Ai的文章,有些人持有Ai取代人工以及失去工作的顾虑。而我从近期的学习发现Ai能够帮我快速的解答问题以及发现问题的根源,同时,能够把原来重复或浪费的时间、精力,拿到学习新的知识上去。

当然Ai也不是尽善尽美的,有时一些疑问,Ai也会一错再错,并且会不断道歉并纠其上一个答复的偏差,但已经能在工作生产力中有很强的体现,而我也在学习前端、服务器等知识时,已经很难离开Ai的帮助。因为,遇到一个问题,Ai可以快速帮我定位并解答,而从网上查阅文章时,需要消耗很多无用的工作量,而且网上问答的质量参差不齐,并且不是每一个答案都适用你。

当Ai无法解答时,就只能从网上查阅文章了,这是最后的退路。网上也没有的话,就无解了。

如果您认为这篇文章给您带来了帮助,您可以在此通过支付宝或者微信打赏网站开放者。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注