使用deitormd

使用deitormd

实现步骤

  • 准备一个添加页面的静态页面
  • 把添加页面对应样式和css和js进行对应引入,同时把vue/jquery引入
  • 添加springmvc的理由跳转到添加页面
  • 在首页添加一个新增文章的按钮,跳转到springmvc指定的路由
  • 引入md编辑器
  • 实现保存文章的功能
  • 实现md编辑器的文章上传的功能。

- 下载md编辑器 -

准备工作

官网:editormd地址
下载:https://pandao.github.io/editor.md/

在这里插入图片描述

官网案例
<link rel="stylesheet" href="editormd/css/editormd.css" />
<div id="test-editor">
    <textarea style="display:none;">### 关于 Editor.md

**Editor.md** 是一款开源的、可嵌入的 Markdown 在线编辑器(组件),基于 CodeMirror、jQuery 和 Marked 构建。
    </textarea>
</div>
<script src="https://cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script>
<script src="editormd/editormd.min.js"></script>
<script type="text/javascript">
    $(function() {
        var editor = editormd("test-editor", {
            // width  : "100%",
            // height : "100%",
            path   : "/editormd/lib/"
        });
    });
</script>

- 准备一个添加页面的静态页面

在这里插入图片描述

- 把添加页面对应样式和css和js进行对应引入,同时把vue引入

- 添加springmvc的理由跳转到添加页面

@Controller
@Slf4j
public class BlogController {

    @GetMapping("/blog/add")
    public ModelAndView toAdd(){
        // 3: 定义模型视图
        ModelAndView modelAndView = new ModelAndView();
        // 2: 指定跳转的页面
        modelAndView.setViewName("/blog/add");
        return modelAndView;
    }
}

上面代码一定要注意:注解一定是@Controller。如果有异步的方法,就在需要异步的方法上增加@ResponseBody.+

访问:http://localhost:8888/blog/add

在这里插入图片描述

注意css/js路径一定要增加/

  <link rel="stylesheet" type="text/css" href="/editormd/css/editormd.css" />
  <script src="/js/jquery.min.js"></script>
  <script src="/editormd/editormd.js"></script>

editormd的路径记得修改一下:

    path: '/editormd/lib/',

- 在首页添加一个新增文章的按钮,跳转到springmvc指定的路由

<div class="square-operation-detail" style="position: relative">
    <div style="position:absolute;right:0;z-index: 110"><a href="/blog/add">添加文章</a></div>
</div>

- 实现保存文章的功能

添加后端新增文章的接口
 /**
     * 新增和添加文章接口
     *
     * @param blog
     * @return
     */
    @PostMapping("/api/blog/saveupdate")
    @ResponseBody
    public Blog saveBlog(@RequestBody Blog blog) {
        boolean flag = blogService.saveOrUpdate(blog);
        return flag ? blog : null;
    }

注意1:添加是一种异步交互处理,所以一定要记得增加@ResponseBody
注意2:axios的默认的post参数的接受是一种:application/json的类型,所以如果接口的参数一个bean就必须在签名增加@RequestBody才能将参数注入到对象中。JQuery不需要,因为JQuery默认的 post参数是:application/xxxx-form-urlencoding,所以springmvc参数注入对象不不需要增加@RequestBody

定义一个div#app
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8" />
    <title></title>
    <link rel="stylesheet" type="text/css" href="/editormd/css/editormd.css" />
    <link rel="stylesheet" type="text/css" href="/css/add.css" />
</head>
<body>
<div id="app">
    <div id="main" class="yykk_editbox">
    <div class="article-head clearfix">

        <select name="topicCategoryId" class="article-title" id="category" style="width: 180px;">
            <option value="1">程序人生</option>
            <option value="10">面试</option>
            <option value="11">数据库</option>
            <option value="12">安全</option>
            <option value="13">测试</option>
            <option value="2">管理</option>
            <option value="3">教程</option>
            <option value="4" selected="selected">学习笔记</option>
            <option value="5">踩坑记录</option>
            <option value="6">架构</option>
            <option value="7">后台</option>
            <option value="8">前端</option>
            <option value="9">问答</option>
        </select>
        <input type="text" id="article_title" class="article-title" placeholder="请在此输入标题" style="width: 28%; ">
        <input type="text" id="article_title-desc" class="article-title" placeholder="用一句话描述此文章" style="width: 50%; font-weight:400;font-size: 12px;position: relative;top:-2px;">
        <span class="publish-btn js-article-publish">发表</span>
    </div>
    <!-- 文章的主体内容 textarea -->
    <div id="article-content"> </div>
</div>
</div>
<script src="/js/jquery.min.js"></script>
<script src="/editormd/editormd.js"></script>
<script src="/js/vue.global.js"></script>
<script src="/js/axios.min.js"></script>
<script src="/js/blog/add.js"></script>
</body>
</html>
定义add.js并初始化一个vue实例
const vm = Vue.createApp({
    // 数据模型
    data(){
        return {

        }
    },

    // 生命周期
    mounted(){

    },

    // 事件定义
    methods:{

    }
}).mount("#app");
如何获取md的html和md标记格式内容
 // 1:获取文本编辑器的内容
 this.blog.htmlcontent = testEditor.getHTML();
 this.blog.content = testEditor.getMarkdown();
 // 2:获取分类标题名称
 this.blog.categoryTitle = this.getCategoryTitle(this.blog.categoryId);
通过axios进入异步请求保存文章到数据库中
 // 3: 执行异步请求
 axios.post("/api/blog/saveupdate",this.blog).then(res=>{
 console.log(res)
 })
完整的JS
//初始化编辑器
var testEditor;
$(function() {
    testEditor = editormd("article-content", {
        width: "100%",
        height: "82vh",
        path: '/editormd/lib/',
        theme: "white",
        previewTheme: "white",
        editorTheme: "pastel-on-white",
        markdown: "",
        codeFold: true,
        saveHTMLToTextarea: true, // 保存 HTML 到 Textarea
        searchReplace: true,
        //watch : false,                // 关闭实时预览
        htmlDecode: "style,script,iframe|on*", // 开启 HTML 标签解析,为了安全性,默认不开启
        //toolbar  : false,             //关闭工具栏
        //previewCodeHighlight : false, // 关闭预览 HTML 的代码块高亮,默认开启
        emoji: true,
        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() {
//                        this.fullscreen();
//                        this.unwatch();
//                        this.watch().fullscreen();
//
//                        this.setMarkdown("#PHP");
//                        this.width("100%");
//                        this.height(480);
//                        this.resize("100%", 640);

//获取编辑器内容

//                testEditor.gotoLine(90); //转到第90行
//
//                testEditor.show(); //显示编辑器
//
//                testEditor.hide(); //隐藏编辑器
//
//                alert(testEditor.getMarkdown()); //获取编辑器内容(不含html)
//
//                alert(testEditor.getHTML()); //获取编辑器html内容
//
//                testEditor.watch(); //开启双窗口对比
//
//                testEditor.unwatch(); //取消双窗口对比
//
//                testEditor.previewing(); //预览效果
//
//                testEditor.fullscreen(); //全屏(按ESC取消)
//
//                testEditor.showToolbar(); //显示工具栏
//
//                testEditor.hideToolbar(); //隐藏工具栏
//
//                testEditor.config({
//                    tocDropdown: true,
//                    tocTitle: "目录 Table of Contents",
//                }); //TOC下拉菜单
//
//                testEditor.config("tocDropdown", false); //TOC默认
        }
    });


});



const vm = Vue.createApp({
    // 数据模型
    data(){
        return {
            blog:{
                id:"",//新增的时候是null,修改时候是有具体的id
                title:"",
                categoryId:"1",
                categoryTitle:"程序人生",
                htmlcontent:"",
                content:"",
                description:""
            },
            categoryList:[
                {id:1,name:"程序人生",checked:false},
                {id:2,name:"Java",checked:false},
                {id:3,name:"Web",checked:'selected'},
                {id:4,name:"数据库",checked:false}
            ]
        }
    },

    // 生命周期
    mounted(){

    },

    // 事件定义
    methods:{

        // 这个方法就是专门获取分类名称
        changeCategory(ev){
            var selectIndex = ev.target.selectedIndex;
            var options = ev.target.options;
            this.blog.categoryId = options[selectIndex].value;
            this.blog.categoryTitle = options[selectIndex].text;
        },

        getCategoryTitle(categoryId){
            // var obj = {};
            // // 根据数据库查询出来的分类组合对象
            // for(let i=0;i<this.categoryList.length;i++){
            //     obj[this.categoryList[i].id] =  this.categoryList[i].name;
            // }
            // // 目的是方便获取
            // return obj[categoryId];

            // 根据数据库查询出来的分类组合对象
            var title = "";
            for(let i=0;i<this.categoryList.length;i++){
                if(this.categoryList[i].id  == categoryId){
                    title = this.categoryList[i].name;
                    break;
                }
            }
            // 目的是方便获取
            return title;
        },

        saveBlog:function(){
            // 1:获取文本编辑器的内容
            this.blog.htmlcontent = testEditor.getHTML();
            this.blog.content = testEditor.getMarkdown();
            // 2:获取分类标题名称
            this.blog.categoryTitle = this.getCategoryTitle(this.blog.categoryId);
            // 3: 执行异步请求
            axios.post("/api/blog/saveupdate",this.blog).then(res=>{
                console.log(res)
            })
        }
    }

}).mount("#app");

总结

  • 修改和添加它们其实是可以公用一个页面的。它的区别只在一个:是否有id,如果有id就是修改,如果没有id就是新增。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值