ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【看后必会】一步步教你用React写一个markdown实时编辑器!

2021-07-05 18:30:36  阅读:483  来源: 互联网

标签:markdown 教你用 marked React hljs import highlight true


1. 实现效果

最近在用React写一个博客管理系统,有一个功能是添加新文章。在新建文章的页面,我希望做到像CSDN这样,左边是编辑区(markdown格式),右边是预览区。实时更新,编辑文本的同时,在预览区就能看到效果。

就自己动手实现了一个这样的组件,markdown实时预览编辑器

具体效果如下:

2. 实现过程

使用React实现,做成单独的一个组件。

首先HTML结构如下:

<header>基于React的markdown实时编辑器</header>
<div className="marked">
    {/* 编辑区 */}
    <div className="input-region markdownStyle"></div>
    {/* 预览区 */}
    <div className="show-region markdownStyle"></div>
</div>

稍微写一点样式,让编辑区和预览区左右布局。

定义一个hook,存储输入的内容:

const [text, setText] = useState('');

左边编辑区,让一个div可编辑,给其加上contentEditable属性,并让值为plaintext-only,表示编辑区域只能输入纯文本

<div className="input-region markdownStyle" contentEditable="plaintext-only"></div>

为什么不用textarea

div高度可自适应,可以拿到纯文本。

当左边编辑区内容改变时,将输入的纯文本存入到state,给编辑区的div加上onInput属性,通过事件对象拿到纯文本:

<div
    className="input-region markdownStyle"
    contentEditable="plaintext-only"
    onInput={e => {
        setText(e.target.innerText);
    }}
></div>

要渲染成markdown格式的内容,就需要插件来渲染,这里使用marked,代码高亮也有需求,使用highlight.js

yarn add marked highlight.js
import marked from 'marked';
import hljs from 'highlight.js';

配置markedhighlight

useEffect(() => {
    // 配置highlight
    hljs.configure({
        tabReplace: '',
        classPrefix: 'hljs-',
        languages: ['CSS', 'HTML', 'JavaScript', 'Python', 'TypeScript', 'Markdown'],
    });
    // 配置marked
    marked.setOptions({
        renderer: new marked.Renderer(),
        highlight: code => hljs.highlightAuto(code).value,
        gfm: true, //默认为true。 允许 Git Hub标准的markdown.
        tables: true, //默认为true。 允许支持表格语法。该选项要求 gfm 为true。
        breaks: true, //默认为false。 允许回车换行。该选项要求 gfm 为true。
    });
}, []);

引入github风格的代码高亮主题,但我自己又稍作了修改:

import './github-dark.css';

在预览区,使用React的标签属性dangerouslySetInnerHTMl来显示内容:

<div
    className="show-region markdownStyle"
    dangerouslySetInnerHTML={{
        __html: marked(text).replace(/<pre>/g, "<pre id='hljs'>"),
    }}
></div>

调用marked将文本渲染成markdown格式的内容。后面加replace是因为,我发现渲染过后不显示代码框背景色,就在<pre>标签加上了id,然后自己写了CSS,让其显示代码框背景。

整个组件写好之后,最终的代码:

import { useState, useEffect } from 'react';
import marked from 'marked';
import hljs from 'highlight.js';
import './github-dark.css';
import './index.css';

const Marked = () => {
    const [text, setText] = useState('');
    useEffect(() => {
        // 配置highlight
        hljs.configure({
            tabReplace: '',
            classPrefix: 'hljs-',
            languages: ['CSS', 'HTML', 'JavaScript', 'Python', 'TypeScript', 'Markdown'],
        });
        // 配置marked
        marked.setOptions({
            renderer: new marked.Renderer(),
            highlight: code => hljs.highlightAuto(code).value,
            gfm: true, //默认为true。 允许 Git Hub标准的markdown.
            tables: true, //默认为true。 允许支持表格语法。该选项要求 gfm 为true。
            breaks: true, //默认为false。 允许回车换行。该选项要求 gfm 为true。
        });
    }, []);
    return (
        <>
            <header>基于React的markdown实时编辑器</header>
            <div className="marked">
                <div
                    className="input-region markdownStyle"
                    contentEditable="plaintext-only"
                    // suppressContentEditableWarning
                    onInput={e => {
                        setText(e.target.innerText);
                    }}
                ></div>
                <div
                    className="show-region markdownStyle"
                    dangerouslySetInnerHTML={{
                        __html: marked(text).replace(/<pre>/g, "<pre id='hljs'>"),
                    }}
                ></div>
            </div>
        </>
    );
};

export default Marked;

3. 源代码

其他代码,如代码高亮主题文件样式文件,包括整个源代码,都放到了[Github]上,需要自取。

如果对你有帮助,帮忙点个小心心❤️~


标签:markdown,教你用,marked,React,hljs,import,highlight,true
来源: https://blog.csdn.net/Jack_lzx/article/details/118495763

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有