React项目,一:markdown编辑器

在之前的React官网教程中,提到了用Remarkable为插件的markdown评论框。现在就来正儿八经地用另外一个插件marked.js做一个markdown编辑器吧!

准备工作

或许在做之前,应该布个局。

<div class="brand">
        <h1>Markdown Previewer</h1>
    </div>

    <div id=container>
        <div >
            <div class="edit-area">
                <textarea placeholder="请输入markdown文本" class="editor"></textarea>
            </div>
            <div class="shower">

            </div>
        </div>
    </div>
/*simple css-reset*/
*{
        margin: 0;
        padding: 0;
}
ul{
        list-style: none;
}
a{
        text-decoration: none;
}

/*major*/
.brand{
        width: 100%;
        height: 80px;
        background: rgb(21,127,178);
}
.brand h1{
        text-align: center;
        font-size: 30px;
        color: #fff;
        line-height: 80px;
        font-weight: normal;
}
#markdownApp{
        width: 100%;
}
.edit-area,.shower{
        float: left;
        width: 50%;
}
.edit-area textarea{
        max-width: 80%;
        min-width: 80%;
        margin: 20px;
        min-height:600px;
        border: 1px solid rgb(21,127,178)
}

大概这样就OK了。

本demo使用的是以下环境(marked.js,highlight.js及其样式库)。

       <link rel="stylesheet" type="text/css" href="css/css.css"/>
    <link rel="stylesheet" href="css/bootstrap.min.css">
    <!-- 高亮样式库,为了让样式总体好看,使用bootstrap的样式库 -->

    <script src="js/react.js"></script>
    <script src="js/react-dom.js"></script>
    <script src="js/browser.min.js"></script>
    <script src="js/marked.js"></script>


    <script src="js/highlight.pack.js"></script>
    <script >hljs.initHighlightingOnLoad();</script>
    <script src="js/js.js"></script>

关于marked.js的设置用法参见marked.js简明手册

基本实现

基本上就是keyUp事件:

 var rendererMD = new marked.Renderer();
    marked.setOptions({
      renderer: rendererMD,
      highlight: function (code) {
          return hljs.highlightAuto(code).value;
      },
      gfm: true,
      tables: true,
      breaks: false,
      pedantic: false,
      sanitize: false,
      smartLists: true,
      smartypants: false
    });

    var markdownString = '```js\n console.log("hello"); \n```';



    var oEditor=document.getElementById('editor');
    var oShower=document.getElementById('shower');
    //oShower.innerHTML=marked(markdownString)

    oEditor.onkeyup=function(){
        oShower.innerHTML = marked(this.value);
    }

React思路

静态结构

按照html结构先把静态结构写上去:

var MarkdownApp=React.createClass({
            render:function(){
                return (
                    <div >
                        <Editor />
                        <div className="shower" ></div>
                    </div>
                );
            }
        });

        var Editor=React.createClass({
            render:function(){
                return (
                    <div className="edit-area">
                        <textarea placeholder="请输入markdown文本" ></textarea>
                    </div>
                );
            }
        });

        ReactDOM.render(
            <MarkdownApp/>,
            document.getElementById('container')
        )

动态实现

var str="Heading\n=======\n\nSub-heading\n-----------\n \n### Another deeper heading\n \nParagraphs are separated\nby a blank line.\n\nLeave 2 spaces at the end of a line to do a  \nline break\n\nText attributes *italic*, **bold**, \n`monospace`, ~~strikethrough~~ .\n\nShopping list:\n\n  * apples\n  * oranges\n  * pears\n\nNumbered list:\n\n  1. apples\n  2. oranges\n  3. pears\n\nThe rain---not the reign---in\nSpain.\n\n *[Herman Fassett](https://freecodecamp.com/hermanfassett)*\n```javascript\nfunction(){\n  alert(hehe);\n}\n```"




        var MarkdownApp=React.createClass({
            getInitialState:function(){
                return {
                    content:str,
                }
            },
            handleChange:function(value){
                this.setState({
                    content:value,
                });

            },
            render:function(){
                return (
                    <div >
                        <Editor
                            handleChange={(value)=>this.handleChange(value)}
                            value={this.state.content}/>
                        <Shower content={this.state.content} />
                    </div>
                );
            }
        });

        var Editor=React.createClass({
            handleChange:function(e){
                var _this=e.target;
                this.props.handleChange(_this.value);
            },
            render:function(){
                return (
                    <div className="edit-area">
                        <textarea
                            placeholder="请输入markdown文本"
                            
                            className="editor"
                            value={this.props.value}
                            onChange={this.handleChange}>
                        </textarea>
                    </div>
                );
            }
        });

        var Shower=React.createClass({
            convertor:function(content){

                var rendererMD = new marked.Renderer();
                marked.setOptions({
                  renderer: rendererMD,
                  highlight: function (code) {
                      return hljs.highlightAuto(code).value;
                  },
                  gfm: true,
                  tables: true,
                  breaks: true,
                  pedantic: false,
                  sanitize: true,
                  smartLists: true,
                  smartypants: false
                });

                //console.log(marked(content));
                return ({
                    __html:marked(content)
                });//注意是两个下划线!
            },
            render:function(){
                return (
                    <div
                        className="shower"
                        
                        dangerouslySetInnerHTML={this.convertor(this.props.content)}></div>
                );
            }
        });

        ReactDOM.render(
            <MarkdownApp/>,
            document.getElementById('container')
        );

看了一下,确实不用怎么想。