12月17, 2016

Clean Blog by Node && React 4

前言

开始实战

markdown富文本编辑器的使用

之前一直在说api前后端路由的书写方式,从来没有注重过前端某些样式。这里由于用到了clean-blog这个主题,所以在样式上没有太多修改。但是,有些功能该主题不支持的,比如富文本编辑器。为了找一个顺手的markdown富文本编辑器,我也是煞费苦心。在此记录下自己折腾后的总结。

首先来看下最终效果

Alt text

如何在项目中引用

  1. 通过bower下载该开源项目代码和依赖
bower install --save editormd
  1. /view/index.ejs中引用其必要的css、js文件 注意: 这里会依赖jquerybootstrapcss,所以都需要作为前提引入
<link rel="stylesheet" href="/bower_components/editor.md/css/editormd.min.css" />
<script src="/bower_components/editor.md/editormd.min.js"></script>
  1. 在页面添加一个有iddiv元素,在这里我暂时起名为myEditor,在/views/index.ejs添加如下代码
var testEditor;
testEditor = editormd("myEditor", {
    width   : "100%",
    height  : 640,
    emoji : true,
    path    : "../../bower_components/editor.md/lib/"
});

简单解释一下这段代码的用处。该段代码,在idmyEditordiv中插入了一个classNametestEditortextarea,

属性名 含义 备注
width textarea的宽度
height textarea的高度
emoji 是否开启emoji表情 开启后可以选择输入,但是不翻墙很难加载出来表情
path 依赖包所在路径 由于该编辑器依赖requirejs,所以直接输入包的相对路径即可引用其他css/js文件

这样做就已经万事俱备了吗? 当然不可能!

如果我们不是单页应用,完全可以在添加博客页面增加这样的代码;但是恰恰我们是单页应用,虽然我们在/views/index.ejs都可以当做全局引入来作为依赖(其实我们更应该压缩为一个js文件),但是,由于该插件是动态插入<textarea></textarea>,当我们没有切到文章提交页面时,还没有加载改页面的html代码,插件找不到id为myEditor的div,所以会抛出myEditor为undefined的错误。那么,如何在文章提交页引入,成为了我们下一步要解决的问题。

其实很简单,我们只需要在页面html加载完成是执行该方法即可。因此我们新建/beComponents/TextArea, 在componentDidMount方法中加入该段代码即可。如下代码所示。

componentDidMount() {
    var testEditor;
    testEditor = editormd("myEditor", {
        width   : "100%",
        height  : 640,
        emoji : true,
        path    : "../../bower_components/editor.md/lib/"
    });
}
render() {
    return (
        <div className="form-group">
            <label htmlFor="content">内容</label>
            <div id="myEditor"></div>
        </div>
    )
}

后端文章提交API书写

静态页面设置完成后,可以在里面书写一些内容。例如下图所示。

Alt text

如何执行提交操作,并且插入数据库呢?

从先前的例子中都可以看到,我所设计的文档都是通过Fetch API去接受JSON数据,同样,我也会以JSON的形式提交数据。

根据上一篇文章,提交文章的代码如下。

app.post("/api/post", function(req, res) {
    let model = req.body;
    var db = mongoose.createConnection("localhost", "article");
    db.once("open", function(err) {
        var Article = mongoose.model("articles", articleSchema);
        var article = new Article(model);
        article.save(model);
        if(err) {
            return err;
        }
        res.send({
            code : 0,
            msg: "success"
        })
    });
})

这里,我通过req.body来接收提交的数据,并且,当数据返回时,返回给客户端这样的JSON字符串.

{
    code: 0,
    message: "success"
}

前端文章提交代码的书写

首先要获取数据,并且对数据进行初步校验,即客户端校验。

submitHandler(e) {
    e.preventDefault();
    let _this = this,
    model = this.state.model;
    model.content = $(".editormd-markdown-textarea").val();

    for(var i in model) {
        if(model[i] == "" || model[i].toString().length === 0) {
            switch (i) {
                case "author":
                    alert("作者未填写");
                    break;
                case "abstract":
                    alert("摘要未填写");
                    break;
                case "title":
                    alert("标题未填写");
                    break;
                case "content":
                    alert("内容未填写");
                    break;
                default:
                    // nothing
            }
            return false;
        }
    }

校验完成之后,提交数据。依然通过Fetch API提交JSON数据.提交成功后,弹出确认框,给予提示。

fetch("http://localhost:3000/api/post", {
         method: "POST",
         headers: {
             "Content-Type": "application/json"
         },
         body: JSON.stringify(model)
     }).then((res) => {
         if(res.ok) {
             $("#myModal").modal("show");
             $(".editormd-markdown-textarea").text("");
             _this.setState({
                 model: {
                     author: "beace",
                     abstract: "",
                     title: "",
                     content: ""
                 }
             });
         }else if (res.status === 401) {
             alert("Oops! You are not authorized.");
         }
     }, function(e) {
         alert("Error submitting form!");
     })
 }

文章详情API书写

当完成提交文章的操作之后,数据库中多了一行记录,如何访问该记录呢?这不得不到了了解文章详情的地步。

我们在第三次记录的时候就已经将后端路由书写完成,大概是这样的。

app.get("/post/:id", function(req, res) {
    res.send(doc);
})

但是,没有定义具体的实现方法,其实,和列表大同小异,只不过,列表中返回的是对象数组的格式(find()方法);在这里,只需要返回一个对象(findOne()方法)。

app.get("/post/:id", function(req, res) {
   var postId = req.params.id;
   var db = mongoose.createConnection("localhost", "article");
   db.once("open", function() {
       var Article = mongoose.model("articles", articleSchema);
       Article.findOne({
           _id: postId
       }, function(err, doc) {
           if (err) console.log(err);
           else {              
               res.send(doc);
           }
       })
   });
})

这样,本篇文章所记录的东西就完成了。

总结

本篇文章记录了开源markdown编辑器的使用,以及其使用方式。并且,将提交文章和文章详情的后端接口书写完成。下一篇,将着重介绍后端如何处理markdown格式的字符串,并且介绍一下react中是如何直接输出html的。

本文链接:https://beacelee.com/post/clean-blog-react-node-4.html

-- EOF --

Comments

评论加载中...

注:如果长时间无法加载,请针对 disq.us | disquscdn.com | disqus.com 启用代理。