1、背景

在做毕业设计,做的是一个博客的个人网站,用到的技术有springboot 、vue,项目中博客的编写用的是editor.md这个富文本,是开源的项目,这是项目地址,可以点进去下载使用,

2、问题记录

1、开始使用 editor.md

1、下载插件放在vue项目的static目录下

2、index.html(注意引用css 和js文件的路径)


<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <title>mu's blog</title>
    <link rel="icon" href="static/favicon.ico" type="image/x-icon">
    <link rel="stylesheet" href="static/editor.md-master/css/editormd.min.css">
    <script src="./static/editor.md-master/examples/js/jquery.min.js"></script>
    <script src="static/editor.md-master/lib/marked.min.js"></script>
    <script src="static/editor.md-master/lib/prettify.min.js"></script>
    <script src="static/editor.md-master/lib/raphael.min.js"></script>
    <script src="static/editor.md-master/lib/underscore.min.js"></script>
    <script src="static/editor.md-master/lib/sequence-diagram.min.js"></script>
    <script src="static/editor.md-master/lib/flowchart.min.js"></script>
    <script src="static/editor.md-master/lib/jquery.flowchart.min.js"></script>
    <script src="./static/editor.md-master/editormd.js"></script>
  </head>
  <body>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
  <style>
    *{
      margin:0;
      padding:0;
    }
  </style>
</html>

说明:这是vue 中的index.html 文件,引用了插件中的一些css和js文件,这些文件引用的顺序最好和我这个一样,因为一开始我引用这些文件的时候顺序是乱的,不是这个顺序,导致有些功能无法实现,但有一个东西是确定的,jqury.min.js文件的引用肯定是引用的js文件的第一个,因为editor.md这个插件是基于jquery的

2、 创建一个组件(新建一个vue文件)
test.vue

<template>
  <div>
    <div id="layout">
      <div id="blog_editormd" style="margin-top: 5px;">

        <textarea style="display: none;">[TOC]</textarea>

      </div>
    </div>

  </div>
</template>

<script>
  export default {
    data() {
      return {
		blogEditor:{}
      }
    },
    methods: {

    },
    created(){
      var _this = this;
      _this.$nextTick(() =>{
        const blogEditor = editormd("blog_editormd",{
          placeholder : '欢迎使用editor.md 编辑器',
          width : "100%",
          height : "880",
          syncScrolling : "single",
          emoji :true,
          /* path : '../../../static/editor.md-master/lib/' ,*/
          path : '/static/editor.md-master/lib/',
          //pluginPath:'/plugins',
          saveHTMLToTextarea : true,
          tocm : true,
          tex :true,
          flowChart : true,
          imageUpload : true,
          imageFormats : ["jpg", "jpeg", "gif", "png", "bmp", "webp"],
          imageUploadURL : "",
          //crossDomainUpload : true
          previewTheme: "dark"

          /**设置主题颜色*/
          /* editorTheme: "pastel-on-dark",
           theme: "gray",
           previewTheme: "dark"*/
        });
        //将刚刚定义的对象 存到vue中,用的时候再取出来
        _this.blogEditor = blogEditor;
      });
    }
  }
  </script>

下面是完整的属性配置(具体的属性值有哪些可以百度,或上官网)


 myEditor = editormd("my-editormd", {


 			width: "100%",
            height: 740,
            path: '/Content/editormd/lib/',
             /**设置主题颜色*/
            theme: "dark",
            previewTheme: "dark",
            editorTheme: "pastel-on-dark",
            
            markdown: "",
            codeFold: true,//折叠代码块
            syncScrolling : 'single',
            saveHTMLToTextarea: true,    // 保存 HTML 到 Textarea
            searchReplace: true,
            watch : false,                // 关闭实时预览
            htmlDecode: "style,script,iframe|on*",            // 开启 HTML 标签解析,为了安全性,默认不开启    
            //toolbar  : false,             //关闭工具栏
            //previewCodeHighlight : false, // 关闭预览 HTML 的代码块高亮,默认开启
            emoji: true,//emoji表情,默认关闭
            taskList: true,
            tocm: true,         // Using [TOCM]
            tex: true,                   // 开启科学公式TeX语言支持,默认关闭
            flowChart: true,             // 开启流程图支持,默认关闭
            sequenceDiagram: true,       // 开启时序/序列图支持,默认关闭,
            //dialogLockScreen : false,   // 设置弹出层对话框不锁屏,全局通用,默认为true
            //dialogShowMask : false,     // 设置弹出层对话框显示透明遮罩层,全局通用,默认为true
            //dialogDraggable : false,    // 设置弹出层对话框不可拖动,全局通用,默认为true
            //dialogMaskOpacity : 0.4,    // 设置透明遮罩层的透明度,全局通用,默认值为0.1
            //dialogMaskBgColor : "#000", // 设置透明遮罩层的背景颜色,全局通用,默认为#fff
            imageUpload: true,//图片上传
            imageFormats: ["jpg", "jpeg", "gif", "png", "bmp", "webp"],
            imageUploadURL: "/Center/RichTextUpload",//上传图片接口地址
            //图片上传后的回调处理
            onload: function () {
                //console.log('onload', this);
                //this.fullscreen();
                //this.unwatch();
                //this.watch().fullscreen();

                //this.setMarkdown("#PHP");
                //this.width("100%");
                //this.height(480);
                //this.resize("100%", 640);
            }
                  
                });


!!!注意要配置路由
说明:有了这个组件,富文本就基本可以显示出来了,在组件的created()方法声明blogEditor ,blogEditor 后面的就是editor.md的配置,我用blogEditor接收了一下,这里有3个要注意的地方

1、 配置editor.md的属性要在dom加载完成之后进行配置,在普通的html页面中只要引入jquery,将配置写在script标签的(这是个美元符号,不晓得为什么显示不出来,下面的this.后面也是) ( f u n c t i o n ( ) ) ; 中 就 可 以 , 而 我 用 的 是 v u e , 所 以 将 属 性 的 配 置 写 在 了 t h i s . (function() {}); 中就可以,而我用的是vue ,所以将属性的配置写在了this. (function());vue,this.nextTick(() =>{}中,
2、 配置中可以看到,editor对象有两个参数,第一个是字符串,第二个是一个对象,要注意的是第一个参数,这个参数是组件中textarea 标签父元素的id
3、 配置editor.md属性的时候,属性中path这个属性是要注意的,这个属性的值就是插件中lib文件夹的相对路径,代码中有一行注释了的path,这个是我在本地运行时用到的一个相对路径,但打包发布后报404,这是因为vue项目打包后 就只有一个static文件夹,一个html文件,项目在访问的时候是直接访问static文件夹的,反正打包前根据组件相对定位是可以用的,具体的试下就晓得,我也记不太清了(这个路径在项目部署的时候还有一个坑,这个我写在另一篇文章中)

到此富文本的框就显示出来了,下面讲下怎么获取富文本中输入的内容
2、获取富文本中输入的内容以及插件根据内容生成的一些标签代码(html的)

注:这里用到了上边代码中的blogEditor 对象,我这里是直接把它存到了vue对象中,这样我在该组件的其他地方就可以使用blogEditor 进行一系列操作了

  1. 获取输入的内容(用户输入),var inputContent = _this.blogEditor.getMarkdown();
  2. 获取插件生成的html代码, var htmlContent = _this.blogEditor.getHTML(); 注意,要获取插件生成html代码要设置属性 saveHTMLToTextarea: true,

这些方法在源码中都有,也就是editormd.js文件,代码中对其中定义的方法也都写了注释,有兴趣的话可以看下

内容也获取到了,下面讲下富文本框上方的工具栏的使用及相关配置

这个是富文本的编辑框
这个图太大了,下面讲的话就只截工具栏

3、工具栏的使用及相关配置配置

1、自定义工具栏

这个我没有自定义,所以没什么说的,下面是官方给的例子

https://pandao.github.io/editor.md/examples/custom-toolbar.html
2、表情
表情
(1)配置emoji: true 属性
(2)下载本地表情包 ,地址:https://github.com/SemiWarm/SemiWarmAdminPhotos/blob/master/emoji.zip
(3)将下载的表情包解压放到 插件目录/plugins/emoji-dialog/下面
(4)修改editormd.js 的emoji表情包路径

editormd.emoji = {  
        //path  : "http://www.emoji-cheat-sheet.com/graphics/emojis/",  
        path  : "/static/editor.md-master/lib/../plugins/emoji-dialog/emoji/",  
        ext   : ".png"  
    }; 
//这个路径有点乱,我这样是可以访问到图片的,网上也有人这样写的
//path  : "../markdown/plugins/emoji-dialog/emoji/", 反正能访问图片到就行

注意:我修改的是editormd.js,我引用的也是editormd.js. 如果要引用editormd.min.js,你需要把修改好了的editormd.js压缩成editormd.min.js再使用

3、表格及有序列表无序列表
在这里插入图片描述
这两个地方我碰到的问题是文章写好后,查看文章时发现这三个东西上面会解析出很多的p标签和br标签
解决方法:
https://github.com/pandao/editor.md/issues/656
上面这篇文章有解决方法,其实后面我发现editormd.js中有两处要改的地方(有两处breaks:true),具体的看上面链接的内容,我两处都改了,问题解决了,只改一个我没试过。
4、图片上传
如果要上传本地图片的话就要后台借口的配合了,插件对后台接口的返回值有要求,要求的是返回json格式的数据,下面是要求返回的字段

{
    success : 0 | 1, //0表示上传失败;1表示上传成功
    message : "提示的信息",
    url     : "图片地址" //上传成功时才返回
}

我用的是springboot,springboot默认返回的是json格式,所以我也没怎么去处理数据的格式,就直接返回了一个类,类里面封装了这三个属性。图片的正常上传这是肯定要实现的,不然其他别谈,图片正常上传后上传图片的那个dialog中第一个输入框就会显示你返回的那个图片地址(上面的url),这个时候你点确定dialog关闭图片是显示不出来的,除非你把图片上传到你的项目目录下(不建议将图片上传到项目目录下),我是将图片上传到盘符中的。具体怎么配置怎么做才能访问到上传到盘符后的图片,看大佬的,我是根据这位大佬的文章解决的这个问题,注意后台接口中的这个东西
@RequestParam(value = “editormd-image-file”, required = false) MultipartFile file
这个下面的文章中也有
https://blog.csdn.net/qq_26641781/article/details/80571264
这里还有一个大坑,图片上传的
现在流行前后端分离,像我这个项目就是这样的,前端和后端不在一起,这个时候你上传图片就会有一个跨域的问题,(报错跨域),这是因为你图片上传后返回的信息插件是给你放到一个iframe下(这个iframe的src就是后台的接口)的,再通过获取iframe元素来获取,前后端分离不用多讲,即使在同一台电脑上,前后端同时运行起来的端口是不可能相同的,这个时候就产生了一个跨域问题(正常情况下,浏览器是不允许在当前域获取另一个域的iframe内容的,如果你针对跨域这一块做了配置那是另外一回事)
解决方法
部署项目,前后端分别打包,把代码扔到一个服务器上去运行,这样就不会再报跨域了(在部署的时候有些东西也是要注意的,不然有些静态资源访问报404,这个我在另一篇文章会讲,慢慢摸索还是可以搞出来的)

5、黑色代码块
这个我也是看别人博客做的,我再叙述一遍也没有这个必要,下面贴出大佬的文章地址
https://www.cnblogs.com/Leo_wl/p/5763491.html
这里想再说点的就是,大佬提供了一个editormd.min.css文件,并不知道她改了哪些东西,虽然他解释了,如果不用黑色代码块的话用插件里的editormd.min.css就行,但要用的话改源码的样式就比较难了,因为
editormd.min.css是压缩了的,看不懂,所以后面调整源码样式的话就只有一个了,覆盖源码的样式,而覆盖源码的样式也有个要注意的地方,以我这个项目为例,我用的是vue, 在style标签有个属性scoped,覆盖的样式不能写在有scoped的style标签中,不然就不覆盖不成功

差点忘了,还有一个就是查看文章,我写的是一个博客项目,所以我就称呼为查看文章

6查看文章
在一开始的index.html中引入了很多的js文件,除了jquery ,editormd.js其他都是查看文章这一块才用到的文件,代码:
view.vue


<template>
  <div>
    <div id="layout">
      <div id="articleView" >
        <textarea style="display: none" name="editormd">{{article.contentHtml}}</textarea>
      </div>
    </div>

  </div>
</template>

<script>
  export default {
    data() {
      return {
		article:{}
      }
    },
    methods: {
      
      getArticleDetail(){
        var _this = this;
        //var articleId = window.sessionStorage.getItem("articleId");
        var articleId = _this.$route.params.articleId;

        _this.$axios.post(`/data/article/detail/${articleId}`).then(res =>{
          var code = res.data.code;
          var message = res.data.message;
          if(code === -1){
            _this.$message.warning(message);
          }else {
            _this.article = res.data.responseData;
            _this.$nextTick(()=>{
              let editorView = editormd.markdownToHTML("articleView", {
                htmlDecode      : "style,script,iframe",  // you can filter tags decode
                emoji           : true,
                taskList        : true,
                tex             : true,  // 默认不解析
                flowChart       : true,  // 默认不解析
                sequenceDiagram : true,  // 默认不解析
              });
            });

          }
        })
      },

    },
    created() {
      var _this = this;
      _this.getArticleDetail();
    }
  }
  </script>

我简单解释下上面的代码,在vue created方法中通过接口查到了要显示的文章信息(上面的textarea放通过getMarkDown(),getHTML()方法获取的内容好像都可以解析),然后再请求的回调中声明一个对象,也讲不出这是个啥,反正就是这样一个东西,跟显示富文本框差不多,至于要不要等DOM加载完成我没试过,我这样写没错,文章可以显示出来

_this.$nextTick(()=>{
              let editorView = editormd.markdownToHTML("articleView", {
                htmlDecode      : "style,script,iframe",  // you can filter tags decode
                emoji           : true,
                taskList        : true,
                tex             : true,  // 默认不解析
                flowChart       : true,  // 默认不解析
                sequenceDiagram : true,  // 默认不解析
              });
            });

7、编辑写好了文章
稍微的讲下这个,这个只要在配置、渲染富文本框的时候,在上面的textarea中双向绑定从数据库中查出来的内容信息就可以了,这是vue的东西,当然也可以用jquery 的 .val()方法将值赋给textarea

到此问题就记录完了

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐