文章目录react-markdown基本配置同步预览配置MdEditorComponent.jsreducer.jsinitBlogState.jsaction-types.jssync-actions.jsstore.jsremark-Gfm配置syntax-highligh配置rehype-katex和remark-math的配置remark-toc...
<a href="#reactmarkdown_7">react-markdown基本配置</a> <a href="#_23">同步预览配置</a>
<a href="#MdEditorComponentjs_27">MdEditorComponent.js</a> <a href="#reducerjs_110">reducer.js</a> <a href="#initBlogStatejs_123">initBlogState.js</a> <a href="#actiontypesjs_146">action-types.js</a> <a href="#syncactionsjs_152">sync-actions.js</a> <a href="#storejs_158">store.js</a> <a href="#remarkGfm_176">remark-Gfm配置</a> <a href="#syntaxhighligh_221">syntax-highligh配置</a> <a href="#rehypekatexremarkmath_267">rehype-katex和remark-math的配置</a> <a href="#remarktoc_304">remark-toc的配置</a> <a href="#rehyperaw_325">rehype-raw的配置</a> <a href="#_347">个性化组件配置</a> <a href="#_362">总结</a>
react-markdown是一款github上开源的适用于react的markdown组件,可以基本实现markdown的功能,且可以根据自己的实际应用定制remark组件。官方给出该组件的好处是:
The two main reasons are that they often rely on dangerouslySetInnerHTML or have bugs with how they handle markdown. react-markdown uses a syntax tree to build the virtual dom which allows for updating only the changing DOM instead of completely overwriting. react-markdown is 100% CommonMark (optionally GFM) compliant and has extensions to support custom syntax.
本文将介绍react-markdown的配置,以及部分实用组件的配置和介绍,包括Katex、syntax-highlighter、Gfm以及TOC。react-markdown的源码和完全介绍请移步https://github.com/remarkjs/react-markdown
使用npm install react-markdown引入react-markdown包,注意该组件的旧版本和新版本使用配置差别较大,我目前为v7.1.0。
一个简单的hello world:
import React from 'react'
import ReactMarkdown from 'react-markdown'
import ReactDom from 'react-dom'
ReactDom.render(<ReactMarkdown># Hello, *world*!</ReactMarkdown>, document.body)
如此以来,简单的react-markdown就配置好啦!但是这种配置支持的语法较少,如表格、代码高亮、数学公式等均不支持,且无法实现同步预览效果。
我使用的是redux来控制状态,当然也可以使用dva或者其他方式。
import React, { Component } from 'react'
import styles from './MdEditorComponent.module.css'
import { connect } from 'react-redux'
import { editMarkdown } from '../../../redux/sync-actions'
import ReactMarkdownComponent from '../article-component/ReactMarkdownComponent'
const DEFAULT_SIZE = 500 //默认代码块高度
class MdEditorComponent extends Component {
constructor (props) {
super(props)
this.state = {
textareaHeight: DEFAULT_SIZE
}
}
componentDidMount () {
window.addEventListener('resize', this.handleResize) //监听resize
}
handleResize = e => {
}
//修改内容状态
handleInputMarkdown = e => {
let previewHeight = this.preview.scrollHeight
let textareaHeight = e.target.scrollHeight
let height = Math.max(previewHeight, textareaHeight, DEFAULT_SIZE)
this.setState({ textareaHeight: height })
this.props.editMarkdown(e.target.value)
}
//当鼠标选中textarea时
handleKeyPressMarkdown = e => {
let previewHeight = this.preview.scrollHeight
let textareaHeight = e.target.scrollHeight
let height = Math.max(previewHeight, textareaHeight, DEFAULT_SIZE)
//下面是自定义的特殊按键触发的效果
if (e.keyCode === 9) {
e.preventDefault()
this.props.editMarkdown(this.props.markdown + '\t')
} else if (e.keyCode === 13)
return false
else if (e.keyCode === 17) { //left ctrl
this.setState({ textareaHeight: height })
} else if (e.keyCode === 8) { //backspace
this.setState({ textareaHeight: height })
} else if (e.keyCode === 192) { // ~
// e.preventDefault()
}
}
render () {
return (
<div className={styles.container} style={{
height: this.state.textareaHeight //设置默认高度
}}>
<div className={styles.input}>
<textarea style={{ border: '0px' }} spellCheck={false} value={this.props.markdown}
onKeyDown={this.handleKeyPressMarkdown}
onChange={this.handleInputMarkdown}/>
</div>
<div ref={div => this.preview = div} className={styles.md}>
<ReactMarkdownComponent content={this.props.markdown}/>
</div>
</div>
)
}
}
//使用redux来控制状态
MdEditorComponent = connect(
({ $BlogState: { mdContent } }) => ({ markdown: mdContent }),
{ editMarkdown }
)(MdEditorComponent)
export default MdEditorComponent
export function $BlogState (state = initBlogState, { data, type }) {
switch (type) {
case EDIT_MARKDOWN:
return { ...state, mdContent: data }
default:
return state
}
}
初始的显示内容
export const initBlogState = {
mdContent: `# Markdown Online Editor
## Subtitle
common content
### Little title
Code Block
### Code Syntax Highlight
~~~js
console.log('hello randyzhang')
~~~
`,
}
export const EDIT_MARKDOWN = 'edit_markdown'
export const editMarkdown = data => actionFactory(EDIT_MARKDOWN, data)
import { applyMiddleware, combineReducers, createStore } from 'redux'
import { composeWithDevTools } from 'redux-devtools-extension'
import thunk from 'redux-thunk'
import { $BlogState } from './reducers'
const store = createStore(
combineReducers({
$BlogState,
}),
composeWithDevTools(applyMiddleware(thunk))
)
export default store
配置好后即可使用表格、删除线、任务列表、引用等操作。需要使用npm install remark-Gfm引入remark-Gfm包。
import React from 'react'
import ReactMarkdown from 'react-markdown'
import ReactDom from 'react-dom'
import remarkGfm from 'remark-gfm'
const markdown = `A paragraph with *emphasis* and **strong importance**.
> A block quote with ~strikethrough~ and a URL: https://reactjs.org.
* Lists
* [ ] todo
* [x] done
A table:
| a | b |
| - | - |
`
ReactDom.render(
<ReactMarkdown children={markdown} remarkPlugins={[remarkGfm]} />,
document.body
)
展示的效果为:
A paragraph with emphasis and strong importance.
A block quote with <sub>strikethrough</sub> and a URL: https://reactjs.org.
Lists <input type="checkbox" class="task-list-item-checkbox" disabled> todo <input type="checkbox" class="task-list-item-checkbox" checked="true" disabled> done
A table:
<table> <thead> <tr> <th>a</th> <th>b</th> </tr> </thead> <tbody></tbody> </table>nn
使用该组件可以实现代码块的彩色,需要使用npm install react-syntax-hightlighter --save来引入react-syntax-highlighter包。
这里components中间的部分主要是针对输入的代码块语言匹配相应的代码高亮,如果非匹配成功则直接使用code形式展示。
import React from 'react'
import ReactDom from 'react-dom'
import ReactMarkdown from 'react-markdown'
import {Prism as SyntaxHighlighter} from 'react-syntax-highlighter'
import {dark} from 'react-syntax-highlighter/dist/esm/styles/prism'
const markdown = `Here is some JavaScript code:
~~~js
console.log('It works!')
~~~
`
ReactDom.render(
<ReactMarkdown
children={markdown}
components={{
code({node, inline, className, children, ...props}) {
const match = /language-(\w+)/.exec(className || '')
return !inline && match ? (
<SyntaxHighlighter
children={String(children).replace(/\n$/, '')}
style={dark}
language={match[1]}
PreTag="div"
{...props}
/>
) : (
<code className={className} {...props}>
{children}
</code>
)
}
}}
/>,
document.body
)
使用该组件可以轻松的翻译输入的数学公式,输入npm install remark-math rehype-katex引入相应的包。
注意:需要使用katex.css来展示相应的效果,否则会出现BUG
需要在index.html中添加上下列的话并下载包:
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.13.13/dist/katex.min.css" integrity="sha384-RZU/ijkSsFbcmivfdRBQDtwuwVqK7GMOw6IMvKyeWL2K5UAlyp6WonmB8m7Jd0Hn" crossorigin="anonymous">
配置的方法为:
import React from 'react'
import ReactDom from 'react-dom'
import ReactMarkdown from 'react-markdown'
import remarkMath from 'remark-math'
import rehypeKatex from 'rehype-katex'
const markdown = ` L = \frac{1}{2} \rho v^2 S C_L`
ReactDom.render(
<ReactMarkdown
children={markdown}
remarkPlugins={[remarkMath]}
rehypePlugins={[rehypeKatex]}
/>,
document.body
)
展示的效果为:
L = 1 2 ρ v 2 S C L L = \frac{1}{2} \rho v^2 S C_L L=21ρv2SCL
该配置可以帮你自动生成markdown的目录,仅需要在开头使用## Table of Content,即可以自动生成。
需要使用npm install remark-toc引入该包。
import React from 'react'
import ReactDom from 'react-dom'
import ReactMarkdown from 'react-markdown'
import remarkToc from 'remark-toc'
ReactDom.render(
<ReactMarkdown
children={markdown}
remarkPlugins={[remarkToc]}
/>,
document.body
)
如果你trusted environment (you trust the markdown),可以使用该配置使markdown支持HTML。需要使用npm install rehype-raw引入该包。
import React from 'react'
import ReactDom from 'react-dom'
import ReactMarkdown from 'react-markdown'
import rehypeRaw from 'rehype-raw'
const input = `<div class="note">
Some *emphasis* and <strong>strong</strong>!
</div>`
ReactDom.render(
<ReactMarkdown rehypePlugins={[rehypeRaw]} children={input} />,
document.body
)
有时候我们需要修改一些颜色、大小等,则可以按照一下规则进行修改:
<ReactMarkdown
components={{
// Map `h1` (`# heading`) to use `h2`s.
h1: 'h2',
// Rewrite `em`s (`*like so*`) to `i` with a red foreground color.
em: ({node, ...props}) => <i style={{color: 'red'}} {...props} />
}}
/>
react-markdown作为一款适用于react的markdown组件,使用非常方便,且丰富的remark和rehype可以扩展很多功能,自己也可以定义remark组件,推荐大家来使用。
如果有好的使用方法或者更适合的组件也可以告诉我,互相学习和进步~
本站主要用于日常笔记的记录和生活日志。本站不保证所有内容信息可靠!(大多数文章属于搬运!)如有版权问题,请联系我立即删除:“abcdsjx@126.com”。
QQ: 1164453243
邮箱: abcdsjx@126.com