在掘金发完来csdn发,一两吃了属于是,以下是正文。
最近在学React,想着做个博客项目练练手,学到了很多东西,在此记录一下。
// markdown编辑器
yarn add for-editor
// 用于显示markdown文章
yarn add react-markdown
// 用于显示目录,不过显示有bug,可以先不下载看后面
yarn add markdown-navbar
// 划线、表、任务列表和直接url等的语法扩展
yarn add remark-gfm
// 解析标签,支持html语法
yarn add rehype-raw
// markdown内容样式,也可以自己写
yarn add github-markdown-css
// 用于高亮代码块
yarn add react-syntax-highlighter
for-editor
import Editor from 'for-editor'
import { useState } from 'react'
const EditArticle = () => {
// 编辑器配置,可以根据自己需要决定是否显示
const toolbar = {
h1: true, // h1
h2: true, // h2
h3: true, // h3
h4: true, // h4
img: true, // 图片
link: true, // 链接
code: true, // 代码块
preview: true, // 预览
expand: true, // 全屏
/* v0.0.9 */
undo: true, // 撤销
redo: true, // 重做
save: true, // 保存
/* v0.2.3 */
subfield: true, // 单双栏模式
}
// 文章内容
const [value, setValue] = useState('')
const handleChange = (val) => {
setValue(val)
}
return (
<div className='editor-box container has-nav'>
<div className='main'>
<Editor className="editor" toolbar={toolbar} value={value} onChange={handleChange} preview={true} subfield={true} />
</div>
</div >
)
}
export default EditArticle
react-markdown
react-syntax-highlighter
在这里预览代码高亮效果
github-markdown.css
import { useState, useEffect } from 'react'
// 文章显示
import ReactMarkdown from 'react-markdown'
// 划线、表、任务列表和直接url等的语法扩展
import remarkGfm from 'remark-gfm'
// 解析标签,支持html语法
import rehypeRaw from 'rehype-raw'
// 代码高亮
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'
// 高亮的主题
import { coldarkDark } from 'react-syntax-highlighter/dist/esm/styles/prism'
// 这里我想方便修改样式,所以没有yarn add github-markdown-css而是直接把这个样式文件放在文件夹里了
import '@/styles/githubMarkdown.css'
const ArticleDetail = () => {
// 这是通过接口拿到的文章
const [articleMsg, setArticleMsg] = useState({})
return (
<div className='article-detail has-nav flex'>
<div className='left-box flex-sub'>
<div className='article-box bg-white'>
<div className='article-body'>
<ReactMarkdown
// 使用github-markdown-css样式的话className必须是markdown-body
className='markdown-body'
// 插件及选项,singleTilde: false表示单波浪线也可以作为擦除线,但我设置true或false都没变化
remarkPlugins={[remarkGfm, { singleTilde: false }]}
rehypePlugins={[rehypeRaw]}
components={{
// 代码高亮
code ({ node, inline, className, children, ...props }) {
const match = /language-(\w+)/.exec(className || '')
return !inline && match ? (
<SyntaxHighlighter
children={String(children).replace(/\n$/, '')}
style={coldarkDark}
language={match[1]}
PreTag="div"
showLineNumbers={true}
{...props}
/>
) : (
<code className={className} {...props} children={children} />
)
}
}}
>{articleMsg.body}</ReactMarkdown>
</div>
</div>
</div>
</div>
)
}
export default ArticleDetail
效果:
样式换成掘金的康康:
markdown-navbar
markdown-navbar很好用,但是有时标题显示会有问题:
bug修复
我的做法是把文件直接拷贝到项目里改完后再引入
import { useState, useEffect } from 'react'
// 有bug所以把文件拷贝在本地自己修改了
import MarkdownNavbar from '@/components/markdownNavbar'
const ArticleDetail = () => {
// 这是通过接口拿到的文章
const [articleMsg, setArticleMsg] = useState({})
return (
<div className='article-detail has-nav flex'>
<div className='article-content basis-xs xs-hide flex'>
<div className='markdown-nav content-sticky bg-white ellipsis'>
<div className='sidebar-title'><span>目录</span></div>
<MarkdownNavbar
className="md-navbar"
source={articleMsg.body}
headingTopOffset={80}
ordered={false} />
</div>
</div>
</div>
</div>
)
}
export default ArticleDetail
修复后: