React Markdown 编辑及渲染解决方案

13,542 阅读4分钟

前言

之前用的富文本编辑框,感觉格式特别乱,写出来的文章布局根本没眼看,代码高亮也没找到合适的。所以一直想着把富文本改为markdown。

插件的选择

我们需要写文章和看文章,所以得有markdown编辑器插件和markdown渲染插件。 github上有很多插件,我最终选定的是for-editorreact-markdown,前者用于编写,后者用于加载。

选择好插件之后,让我们开始在项目中使用吧!

for-editor 安装使用方法

安装

 npm install for-editor --save

使用

代码如下:

import React from 'react'
import Editor from 'for-editor'

class WriteBlog extends React.Component{
  constructor(props){
    super(props)
    this.state = {
      editorValue:'',
      imageUrl:''
    }
  }
  handleChange(value){
    this.setState({
      editorValue:value
    })
  }
  uploadHandler(params){
    fetch.get('getQiniuToken',{
      token:JSON.parse(Cookies.get('loginInfo')).token
    }).then(res=>{
      utils.uploadFile(params,res.data.qiniuToken).then(res=>{
        this.setState({
          imageUrl:'http://img.xuweijin.com/'+res
        })
        let str = this.state.editorValue + '![alt](http://img.xuweijin.com/'+res+')'
        this.setState({
          editorValue:str
        })
      })
    })
  }
  render(){
    return(
      <Editor className="my-editor"
                  subfield = {true}
                  preview = {true}
                  addImg = {(file) => this.uploadHandler(file)}
                  value={this.state.editorValue} onChange={(value) => this.handleChange(value)} />
    )
}

图片上传没有使用官方的方法,上传成功手动往编辑器里加入图片的字符串。

上面只是简单贴了一些代码,具体参数请直接前往for-editor github主页查看。

react-markdown 安装使用办法

安装

npm install --save react-markdown

使用

代码如下:

import React from 'react'
import ReactMarkdown from 'react-markdown'
class BlogDetail extends React.Component{
  constructor(props){
    super(props)
    this.state = {
      articleDetail:'',
    }
  }
  render(){
    return(
      <ReactMarkdown source={this.state.articleDetail.article_content}
                                 escapeHtml={false}></ReactMarkdown>
    )
  }
}

上面只是简单贴了代码,具体配置参数请前往github react-markdown主页查看。


以上就是markdown文本的解决办法,但到此还不算结束,我们解析时还要加上代码高亮,否则当我们文章里有代码时,阅览体验将会极差。

代码高亮

安装代码高亮插件包

我这边选择的是_react-syntax-highlighter_

npm install react-syntax-highlighter --save

使用

  1. 首先新建一个CodeBlock.jsx文件,代码如下
import React, { PureComponent } from "react";
import PropTypes from "prop-types";
import { PrismLight as SyntaxHighlighter } from "react-syntax-highlighter";
// 设置高亮样式
import { xonokai } from "react-syntax-highlighter/dist/esm/styles/prism";
// 设置高亮的语言
import { jsx, javascript, sass, scss } from "react-syntax-highlighter/dist/esm/languages/prism";
class CodeBlock extends PureComponent {
  static propTypes = {
    value: PropTypes.string.isRequired,
    language: PropTypes.string
  };

  static defaultProps = {
    language: null
  };

  componentWillMount() {
    // 注册要高亮的语法,
    // 注意:如果不设置打包后供第三方使用是不起作用的
    SyntaxHighlighter.registerLanguage("jsx", jsx);
    SyntaxHighlighter.registerLanguage("javascript", javascript);
    SyntaxHighlighter.registerLanguage("js", javascript);
  }

  render() {
    const { language, value } = this.props;
    return (
      <figure className="highlight">
        <SyntaxHighlighter language={language} style={xonokai}>
          {value}
        </SyntaxHighlighter>
      </figure>
    );
  }
}
export default CodeBlock;
  1. 解析时使用

根据react-markdown提供的方法,我们在解析md文件是,对code标签进行处理,加入高亮的样式类名,简单贴下代码:

import CodeBlock from '../components/CodeBlock'
class BlogDetail extends React.Component{
  constructor(props){
    super(props)
    this.state = {
      articleDetail:'',
    }
  }
  render(){
    return(
      <ReactMarkdown source={this.state.articleDetail.article_content}
                                 renderers={{
                                   code: CodeBlock
                                 }}
                                 escapeHtml={false}></ReactMarkdown>
    )
  }
}

这样我们就可以看到文章解析时,代码部分会出现高亮样式了。

文章目录

当我们文章过长时,我们需要加入文章目录以便读者对整体有个概览,也方便读者迅速切换到想要了解的部分,类似于掘金这种

alt

通过github,最后找到markdown-navbar这个插件,虽然star数不多,但是使用起来还是很方便的。

markdown-navbar 安装

  npm install markdown-navbar --save

使用

这个插件使用起来还是很方便的,只需要在项目中引入这个插件,然后把需要解析的md文件传入,就会自动生成一个目录树。一般目录树需要固定,所以我这里使用了antd的Anchor组件,将目录固定在了右侧,代码如下:

import { Anchor } from 'antd';
import MarkNav from 'markdown-navbar';
import 'markdown-navbar/dist/navbar.css';
class BlogDetail extends React.Component{
  constructor(props){
    super(props)
    this.state = {
      articleDetail:'',
    }
  }
  render(){
    return(
      <Anchor>
                <div className="markNav-title">文章目录</div>
                <MarkNav
                  className="article-menu"
                  source={this.state.articleDetail.article_content}
                  headingTopOffset={80}
                />
       </Anchor>
    )
  }
}

这里只是简单贴了代码,具体配置还请前往github markdown主页自行查看。

结论

以上就是react markdown语法编辑及渲染整体的解决方案啦,贴一张渲染后的文章图片:

alt

可以看到渲染后的样式还是挺工整的,大功告成!

第一次写这种小长篇,基本都是流水账的形式,非常感谢您能看到最后,最后欢迎您来我的个人主页留言互动~