在 React 中使用 highlight.js 和 Clipboard.js 实现代码块和复制功能

参考链接:https://blog.csdn.net/huangjuan0229/article/details/130319050

在前端开发中,代码块高亮和复制功能是十分常见的需求。而在 React 中,常用的代码高亮库是 highlight.js,常用的复制库是 Clipboard.js。本篇文章将介绍如何在 React 中使用这两个库,实现代码高亮和复制功能。

安装 highlight.js 和 Clipboard.js

首先,在我们的 React 项目中安装 highlight.js 和 Clipboard.js:

npm install highlight.js clipboard --save

注意:
这里的库是highlight.js,不是highlight,博主就因为npm了highlight踩了一些坑,小伙伴们注意一下

安装完成后,我们就可以在 React 中使用这两个库了。
可以在package.json中查看
在这里插入图片描述

配置 highlight.js 支持的语言

highlight.js 支持很多种语言的代码高亮,我们需要配置支持的语言。在本例中,我们只演示部分语言的高亮,可根据自己的需要进行配置。我们创建一个 src/highlight.js 文件:

import hljs from 'highlight.js/lib/core';
// 导入需要的语言高亮
import javascript from 'highlight.js/lib/languages/javascript';
import java from 'highlight.js/lib/languages/java';
import csharp from 'highlight.js/lib/languages/csharp';
import php from 'highlight.js/lib/languages/php';
import python from 'highlight.js/lib/languages/python';
import objectivec from 'highlight.js/lib/languages/objectivec';
import bash from 'highlight.js/lib/languages/bash';
 
hljs.registerLanguage('javascript', javascript);
hljs.registerLanguage('java', java);
hljs.registerLanguage('csharp', csharp);
hljs.registerLanguage('php', php);
hljs.registerLanguage('python', python);
hljs.registerLanguage('objectivec', objectivec);
hljs.registerLanguage('bash', bash);
 
export default hljs;

在这个文件中,我们导入了需要使用的语言高亮,并注册到了 highlight.js 中,最后导出了 hljs 对象。这样,我们就可以在 React 中方便地使用 highlight.js 了。

创建 CodeBlock 组件

我们创建一个 src/components/CodeBlock/index.js 文件,实现 CodeBlock 组件:

import React, { useEffect, useRef, useState } from 'react';
import hljs from '../../highlight';
import Clipboard from 'clipboard';
 
import 'highlight.js/styles/dark.css';
 
export default function CodeBlock({ language, code }) {
  const preRef = useRef(null);
  const [copied, setCopied] = useState(false);
 
  useEffect(() => {
    if (preRef.current) {
      hljs.highlightBlock(preRef.current);
 
      // 创建 clipboard 实例并保存到变量中
      const clipboard = new Clipboard(`#${language}copy_btn`, {
        text: () => code,
      });
 
      // 监听复制成功事件
      clipboard.on('success', () => {
        setCopied(true);
        setTimeout(() => setCopied(false), 2000);
      });
 
      // 销毁 clipboard 实例
      return () => {
        clipboard.destroy();
      };
    }
  }, [code]);
 
  return (
    <div className="code-block" style={{ position: 'relative', marginTop: 8 }}>
      <pre>
        <code id={language} ref={preRef} className={language}>
          {code}
        </code>
      </pre>
      <button id={`${language}copy_btn`} style={{ position: 'absolute', top: 4, right: 4, lineHeight: '14px' }} className="code-block__button" data-clipboard-target={`#${language}`} disabled={!preRef.current}>
        {copied ? '已复制' : '复制'}
      </button>
    </div>
  );
}

在这个组件中,我们使用了 useRefuseEffect 钩子,分别保存了代码块的 DOM 对象和复制按钮的 Clipboard 对象。在 useEffect 中,我们使用 highlight.js 对代码块进行了高亮,并创建了 Clipboard 实例,监听了复制成功事件。当点击复制按钮后,会将代码块的内容复制到剪贴板中,并在按钮上显示“已复制”,2 秒后消失。最后,我们将代码块和复制按钮显示在了页面上。

使用 CodeBlock 组件

参考文献:https://www.02405.com/archives/2045

import React from 'react';
import CodeBlock from '@/components/CodeBlock';
 
export default function BlogPost() {
  const code = `
    import React from 'react';
import CodeBlock from '@/components/CodeBlock';
 
export default function BlogPost() {
  const code = '111';
 
  return (
    <div>
      <CodeBlock language="javascript" code={code} />
    </div>
  );
}
  `;
 
  return (
    <div>
      <CodeBlock language="javascript" code={code} />
    </div>
  );
}

效果展示

在这里插入图片描述

自定义highlight样式

参考文献:
highlight.js中文网: https://fenxianglu.cn/highlight.html?theme=a11y-light
点开上面的链接,我们可以预览highlight的不同风格,我们可以根据自己需要的主题引入对应的style
在这里插入图片描述
在node_modules中的highlight.js下的styles文件是源码内置样式
在这里插入图片描述
页面引入

import 'highlight.js/styles/dark.css';

预览效果

在这里插入图片描述

自定义样式

博主需求要求字体全是绿色的效果,博主看了源码,在本地新建index.less文件,手动修改配置颜色
index.less

pre code.hljs {
  display: block;
  padding: 1em;
  overflow-x: auto;
}
code.hljs {
  padding: 3px 5px;
} /*!
  Theme: a11y-dark
  Author: @ericwbailey
  Maintainer: @ericwbailey

  Based on the Tomorrow Night Eighties theme: https://github.com/isagalaev/highlight.js/blob/master/src/styles/tomorrow-night-eighties.css
*/
.hljs {
  color: #20ff20;
  background: #2b2b2b;
}
.hljs-comment,
.hljs-quote {
  color: #20ff20;
}
.hljs-deletion,
.hljs-name,
.hljs-regexp,
.hljs-selector-class,
.hljs-selector-id,
.hljs-tag,
.hljs-template-variable,
.hljs-variable {
  color: #20ff20;
}
.hljs-built_in,
.hljs-link,
.hljs-literal,
.hljs-meta,
.hljs-number,
.hljs-params,
.hljs-type {
  color: #20ff20;
}
.hljs-attribute {
  color: #20ff20;
}
.hljs-addition,
.hljs-bullet,
.hljs-string,
.hljs-symbol {
  color: #20ff20;
}
.hljs-section,
.hljs-title {
  color: #20ff20;
}
.hljs-keyword,
.hljs-selector-tag {
  color: #20ff20;
}
.hljs-emphasis {
  font-style: italic;
}
.hljs-strong {
  font-weight: 700;
}
@media screen and (-ms-high-contrast: active) {
  .hljs-addition,
  .hljs-attribute,
  .hljs-built_in,
  .hljs-bullet,
  .hljs-comment,
  .hljs-link,
  .hljs-literal,
  .hljs-meta,
  .hljs-number,
  .hljs-params,
  .hljs-quote,
  .hljs-string,
  .hljs-symbol,
  .hljs-type {
    color: highlight;
  }
  .hljs-keyword,
  .hljs-selector-tag {
    font-weight: 700;
  }
}

页面引入

import './index.less';

预览效果
在这里插入图片描述

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值