博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
手把手教你造一个基于React的markdown编辑器
阅读量:6252 次
发布时间:2019-06-22

本文共 2774 字,大约阅读时间需要 9 分钟。

前言

笔者在18年年末的时候接到一个开发任务——搭建一个AI项目的开放平台,其中的产品文档为转化为HTML格式的markdown文档。考虑到文档的即时更新,将文档信息做成了Ajax接口的形式。因此管理后台只需将textarea表单的内容通过markdown解析器进行HTML格式转化,然后将markdown内容和经转化的HTML文档都保存到数据库即可。

基本需求完成后,为了更好的用户体验,考虑将常用的编辑功能添加进来。改进版不仅支持了常用的文本编辑功能,还实现的UI界面的配置化。本着造福伸手党的目的,以及积累些开源经验,笔者将该react 组件 进行了封装改造,并且发布到了开源社区。

预览

在线体验

image

特点

  • 轻量、基于React
  • UI可配置, 如只显示编辑区或预览区
  • 支持常用的markdown编辑功能,如加粗,斜体等等...
  • 支持编辑区和预览区同步滚动

开发心得

  • 文本编辑

    大多数常见的编辑器,包括富文本编辑器,利用了某些元素如div的contenteditable属性,配合selection、range、execCommand等API,实现了富文本编辑功能。这里面的实现比较复杂,所以有了""这个说法。

    而markdown编辑器,核心的处理内容为简单语法的纯文本,复杂度相对来说比较低,并且input标签自带onSelect事件,可以很方便的获取选择信息(选择起始位置和选择文本值),因此要想实现编辑功能,只需将要改动的内容进行文本转换,然后进行重新拼接首尾,大功告成。

  • markdown解析

    考察了几个社区流行的markdown解析器,比较流行的有, , 等等。综合考虑扩展性以及稳定性,笔者选择了markdown-it作为markdown的词法解析器,结果也比较满意。

  • 同步滚动

    当选择分栏编辑的时候,滚动左侧的编辑区,右侧的预览区能自动滚动到对应的区域。方案参考了《》。只需先计算出输入框容器元素与预览框容器元素之间最大scroll范围的比例值,然后根据主动滚动元素自身的scrollTop做相应的比例换算,即可知道对方区域的scrollTop值。

  • 关于UI

    • 项目的字体库选择了Font Awesome风格,并且只选取了项目所需要的一些图标。
    • 编辑器的整体css均可通过全局覆盖的形式进行自定义。目前暂时只支持灰色主题。
    • 编辑器的显示区域包括菜单栏,编辑器,预览区,工具栏,通过配置组件的config属性,可以选择默认的展示区域。

Install

npm install react-markdown-editor-lite --save

Props

Property Description Type default Remarks
value markdown content String ''
style component container style Object {height: '100%'}
config component config Object {view: {...}, logger: {...}}
config.view component UI Object {menu: true, md: true, html: true}
config.imageUrl default image url String ''
config.linkUrl default link url String ''
config.logger logger in order to undo or redo Object {interval: 3000}
onChange emitting when editor has changed Function ({html, md}) => {}

Example

'use strict';import React from 'react'import ReactDOM from 'react-dom'import MdEditor from 'react-markdown-editor-lite'const mock_content = "Hello.\n\n * This is markdown.\n * It is fun\n * Love it or leave it."export default class Demo extends React.Component {  mdEditor = null  handleEditorChange ({html, md}) {        console.log('handleEditorChange', html, md)  }  handleGetMdValue = () => {       this.mdEditor && alert(this.mdEditor.getMdValue())        }  handleGetHtmlValue = () => {        this.mdEditor && alert(this.mdEditor.getHtmlValue())        }  render() {    return (            
this.mdEditor = node} value={mock_content} style={
{height: '400px'}} config={
{ view: { menu: true, md: true, html: true }, imageUrl: 'https://octodex.github.com/images/minion.png' }} onChange={this.handleEditorChange} />
) }}

最后

欢迎大家使用和反馈, (, 你的点赞将是我莫大的动力?

转载地址:http://twfsa.baihongyu.com/

你可能感兴趣的文章
[杂记]如何在LaTeX里插入高亮代码
查看>>
「常微分方程」(阿諾爾德) Page 6 問題4 經過擴張相空間的每一點有且僅有一條積分曲線...
查看>>
同一个闭区间上有界变差函数的和与积都是有界变差函数
查看>>
java安全证书配置
查看>>
使用erlang 建立一个自动化的灌溉系统(1)准备工作
查看>>
python 调用aiohttp
查看>>
mysql 案例~ mysql故障恢复
查看>>
Spring Boot中使用MyBatis注解配置详解
查看>>
MatLab实现FFT与功率谱
查看>>
答《漫话ID》中的疑问:UniqueID和ClientID的来源
查看>>
【转】Asp.net控件开发学习笔记整理篇 - 服务器控件生命周期
查看>>
Linux下的shell编程(一)BY 四喜三顺
查看>>
javascript一些小技巧
查看>>
I00024 出钱买羽
查看>>
linux下文件的一些文件颜色的含义
查看>>
websotrm注册码
查看>>
迭代器(Iterable)和for..in..的三种协议
查看>>
判断浏览器是否为顶层窗口
查看>>
数据结构化与保存
查看>>
跨域iframe高度自适应(兼容IE/FF/OP/Chrome)
查看>>