前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >React 实现一个markdown[1]

React 实现一个markdown[1]

作者头像
用户4793865
发布2023-01-12 16:59:07
7810
发布2023-01-12 16:59:07
举报
文章被收录于专栏:前端小菜鸡yym前端小菜鸡yym

「这是我参与2022首次更文挑战的第19天,活动详情查看:2022首次更文挑战

我想实现类似我们掘金的一个文章发布的markdown,这是我们最后实现的结果

image.png
image.png

使用组件

React的markdown组件有很多我们这里用到的是react-markdown-editor-lite。他是对 MarkdownIt的再次封装。我们其他的Markdown右半部分的效果展示,是需要我们自己去实现的。这个插件会自动许渲染出右边的效果。

npm地址https://www.npmjs.com/package/react-markdown-editor-lite

演示地址https://harrychen0506.github.io/react-markdown-editor-lite/

标题

实现一下我们的标题输入部分,左部分是一个输入框Input,右边是一个div里面里面有一个提交按钮。

image.png
image.png
代码语言:javascript
复制
 return (
    <div className={style.markdown}>
      <div className={style.header}>
        {/* onChange(e)   e.target.value */}
        <Input
          className={style.input}
          size="middle"
          onChange={e => setSubmitParams({ ...submitParams, title: e.target.value })}
        />
        <div className={style.btn_con}>
          <Button type="primary" onClick={showDrawer}>
            发布
          </Button>
        </div>
      </div>
    </div>  
      )

对应的样式

代码语言:javascript
复制
.header{
    display:flex;
}
.input{
    width:70%;
    border:0px;
    font-size:24px;
    font-weight: bold;
}
.btn_con{
    width:30%;
    padding:20px;
    text-align: right;
    background-color:#FFFFFF;
}

添加markedown

需要导入一下内容

代码语言:javascript
复制
import MarkdownIt from 'markdown-it';
import 'react-markdown-editor-lite/lib/index.css';
import MdEditor from 'react-markdown-editor-lite';
代码语言:javascript
复制
return (
    <div className={style.markdown}>
      <div className={style.header}>
        {/* onChange(e)   e.target.value */}
        <Input
          className={style.input}
          size="middle"
          // 改变提交参数的title
          onChange={e => setSubmitParams({ ...submitParams, title: e.target.value })}
        />
        <div className={style.btn_con}>
        // 展示抽屉
          <Button type="primary" onClick={showDrawer}>
            发布
          </Button>
        </div>
      </div>
      <MdEditor
        value={text}
        // 给markdown一个高
        style={{ height: '500px' }}
        // 这个必传 用于右边展示效果的渲染
        renderHTML={text => mdParser.render(text)}
        // 改变markdown内容触发 函数 handleEditorChange 
        onChange={handleEditorChange}
        // 配置html md是否渲染
        config={{
          view: {
            menu: true,
            md: true,
            html: true,
          },
        }}
      />
    </div>  
      )

全屏问题

点击这个全屏图标进入全屏后,发现我们刚才的标题部分不见了

image.png
image.png

审查元素发现是这个Markdown给我们的title内容遮盖住了。这个Markdown的class名是full

image.png
image.png

因此给full添加一个样式,让他距离顶部一个title内容的高度

代码语言:javascript
复制
:global{
    .full {
        top:70px !important;
    }
}

完善组件功能

上面的代码只是在样式上实现了,我们来继续完善功能。

用到的变量

提交参数

这是我们整个页面提交到后端的参数。对应我们的Markdown的有markedown和html

代码语言:javascript
复制
  // 提交参数
  const [submitParams, setSubmitParams] = useState<SubmitParams>({
    html: '',
    markedown: '',
    user_id: '2',
    desc: '',
    title: '',
    user: 'ss',
    date: new Date(),
    type: '',
    column: '',
    cover: '',
    publish: false,
  });

Markdown用到的参数

代码语言:javascript
复制
  // Markdown文本
  const [text, setText] = useState();
  // MarkDown HTML
  const [html, setHtml] = useState();

方法

我们看一下上面的<MdEditor>组件。看他用到的方法

代码语言:javascript
复制
 <MdEditor
        value={text}
        style={{ height: '500px' }}
        // 用于右边展示效果的渲染
        renderHTML={text => mdParser.render(text)}
        onChange={handleEditorChange}
        config={{
          view: {
            menu: true,
            md: true,
            html: true,
          },
      
        }}
      />

mdParser

这个方法是对Markdown的内容处理之后再渲染。这里最后对Markdown中的code内容进行了高亮处理。

代码语言:javascript
复制
// 声明Markdown组件
const mdParser = new MarkdownIt({
  html: true,
  linkify: true,
  typographer: true, // 设置代码高亮的配置
  highlight(code, language) {
    if (language &amp;&amp; hljs.getLanguage(language)) {
      try {
        return `<pre><code class="hljs language-${language}">${hljs.highlight(code, { language }).value}</code></pre>`;
      } catch (__) {}
    }

    return `<pre class="hljs"><code>${mdParser.utils.escapeHtml(code)}</code></pre>`;
  },
});

这里需要引入一些样式样式

代码语言:javascript
复制
 npm install github-markdown-css
代码语言:javascript
复制
// react-markdown-editor-lite中自带了,如果没有需要下载
import hljs from 'highlight.js'; // 引入highlight.js库  代码高亮
import 'highlight.js/styles/github.css'; // 引入github风格的代码高亮样式
// 这个dark风格跟我的有些样式冲突 所以没使用
// import 'highlight.js/styles/dark.css'

实现效果如下

image.png
image.png

handleEditorChange

这是Markdown内容改变触发的函数,html和text分别是Markdown对应的标签和md格式。

代码语言:javascript
复制
  // 文本编辑器内容变化
  const handleEditorChange = ({ html, text }) => {
    //给变量赋值
    setText(text);
    setHtml(html);
    // 这里我们提取标签中的文字然后作为文字简介
    const reg = /<[^<>]+>/g; // 1、全局匹配g肯定忘记写  2、<>标签中不能包含标签实现过滤HTML标签
    const text2 = html.replace(reg, '').replace(/[\r\n]/g,"");
    // 这里将html和desc(文章简介)赋值给提交参数
    // desc进行了截取处理
    setSubmitParams({ ...submitParams, html, desc: text2.slice(0, 100) });
  };

如图我们写一个表格,其对应的html 和 text如下

image.png
image.png

完善上传图片

到这里,我们基本实现了一个Markdown,但是对于Markdown的图片,其实还是需要上传到后端,后端再返回给前端一个地址的

  • onImageUpload={handleImageUpload} 上传图片是触发函数handleImageUpload
  • imageUrl: 'https://octodex.github.com/images/minion.png' 如果上传图片失败返回一个默认图片地址。
代码语言:javascript
复制
  <MdEditor
        value={text}
        style={{ height: '500px' }}
        // 用于右边展示效果的渲染
        renderHTML={text => mdParser.render(text)}
        onChange={handleEditorChange}
        onImageUpload={handleImageUpload}
        config={{
          view: {
            menu: true,
            md: true,
            html: true,
          },
          imageUrl: 'https://octodex.github.com/images/minion.png',
        }}
      />
 

handleImageUpload

代码语言:javascript
复制
async function handleImageUpload(file, callback) {
  const formData = new FormData();
  formData.append('file', file);
  //走接口
  await UploadImage(formData).then(res => {
    callback(res.url);
  });
  const reader = new FileReader();
  // reader.onload = () => {

  // };
  reader.readAsDataURL(file);
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-02-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 使用组件
    • 标题
      • 添加markedown
        • 全屏问题
        • 完善组件功能
          • 用到的变量
            • 提交参数
            • Markdown用到的参数
          • 方法
            • mdParser
            • handleEditorChange
            • handleImageUpload
        • 完善上传图片
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档