实现一个简易版代码编辑预览功能

简易版代码编辑预览功能

前言

最近在使用掘金时候,在想有没有个离线版本的码上掘金呢?这样就能在本地很方便地调试自己的前端demo了,于是说干就干,自己动手实现一个具有代码编辑器和页面预览功能的简易版码上掘金。实现效果图如下所示:

实现一个简易版代码编辑预览功能

介绍

首先,如何实现一个代码编辑器呢,还需要支持高亮显示、代码折叠、突出显示匹配的括号…等功能。当然这就不重复造轮子了,直接站在巨人的肩膀上,经过一番搜索,最终找到了github.com/ajaxorg/ace…

页面结构

一个网页最简单无非就是三个元素,html、css、js。因此直接将上半部分一分为三,下半部分负责展示预览的页面。html框架代码如下:

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>Editor</title>
    <link href="static/css/ace.css" rel="stylesheet">
</head>
<body>
<div id="box">
<div id="top">
    <ul class="layout-code">
        <li>
            <div class="title">HTML代码</div>
            <div class="content">
                <pre id="editorHtml" class="editor"></pre>
            </div>
        </li>
        <li>
            <div class="title">css代码</div>
            <div class="content">
                <pre id="editorCss" class="editor"></pre>
            </div>
        </li>
        <li>
            <div class="title">javascript代码</div>
            <div class="content">
                <pre id="editorJs" class="editor"></pre>
            </div>
        </li>
    </ul>
</div>

<div class="layout-preview" id="bottom">
    <div class="title">效果预览</div>
    <div class="content">
        <iframe id="preview" frameborder="0"></iframe>
    </div>
</div>
<div id="line"></div>
</div>
<script src="static/libs/require.js"></script>
</body>
</html>

引入ACE

使用require,引入ace相关资源,设置编辑器主题以及为不同的代码类型配置代码编辑器,并初始化编辑器中的默认值,具体使用可查看 github.com/ajaxorg/ace

<script>
    require(["ace/ace", "ace/ext/code_lens"], function(ace, codeLens) {
        var option = {
            enableBasicAutocompletion: true,
            enableSnippets: true,
            enableLiveAutocompletion: false
        };
        // html
        var editorHtml = ace.edit("editorHtml");
        editorHtml.session.setMode("ace/mode/html");
        editorHtml.setTheme("ace/theme/chaos");
        editorHtml.setOptions(option);
        editorHtml.setValue("<div id='map'></div>");
        editorHtml.moveCursorTo(0, 0);
        editorHtml.session.on('change', function (e) {
            runAllCodes();
        });
        // css
        var editorCss = ace.edit("editorCss");
        editorCss.session.setMode("ace/mode/css");
        editorCss.setTheme("ace/theme/chaos");
        editorCss.setOptions(option);
        editorCss.setValue("html,\n" +
            "body,\n" +
            "#map {\n" +
            "  width: 100%;\n" +
            "  height: 100%;\n" +
            "  margin: 0;\n" +
            "  padding: 0;\n" +
            "  overflow: hidden;\n" +
            "}");
        editorCss.moveCursorTo(0, 0);
        editorCss.session.on('change', function (e) {
            runAllCodes();
        });
        // js
        var editorJs = ace.edit("editorJs");
        editorJs.session.setMode("ace/mode/javascript");
        editorJs.setTheme("ace/theme/chaos");
        editorJs.setOptions(option);
        editorJs.setValue("document.getElementById('map').innerText = 'Hello World!';");
        editorJs.moveCursorTo(0, 0);
        editorJs.session.on('change', function (e) {
            runAllCodes();
        });

        runAllCodes();

        function runAllCodes() {
            var html = editorHtml.getValue();
            var css = editorCss.getValue();
            var js = editorJs.getValue();

            var code = "<!DOCTYPE html>\n" +
                "<html lang=\"en\">\n" +
                "<head>\n" +
                "  <meta charset=\"UTF-8\">\n" +
                "  <title>Editor</title>\n" +
                "  <style>";
            code += "\n" + css;

            code +=
                "\n  </style>\n" +
                "</head>\n" +
                "<body>\n";
            code += "\n" + html;

            code +=
                "\n  <script>\n";
            code += "\n" + js;
            code +=
                "\n  <\/script>\n" +
                "<\/body>\n" +
                "</html>";
            document.getElementById("preview").setAttribute("srcdoc", code);
        }
    })
</script>

关于预览

我们编辑的代码如何插入到当前页面中,来实现预览呢,答案是使用iframe,iframe可以通过src嵌入外部链接,但可能大部分人不知道的是使用iframe的srcdoc属性,可以嵌入一个完整的html页面代码。我们直接将html、js、css组合拼接通过document.getElementById("preview").setAttribute("srcdoc", code)来将我们自定义的代码渲染到预览窗口上。

<iframe id="preview" frameborder="0"></iframe>


 function runAllCodes() {
    var html = editorHtml.getValue();
    var css = editorCss.getValue();
    var js = editorJs.getValue();

    var code = "<!DOCTYPE html>\n" +
        "<html lang=\"en\">\n" +
        "<head>\n" +
        "  <meta charset=\"UTF-8\">\n" +
        "  <title>Editor</title>\n" +
        "  <style>";
    code += "\n" + css;

    code +=
        "\n  </style>\n" +
        "</head>\n" +
        "<body>\n";
    code += "\n" + html;

    code +=
        "\n  <script>\n";
    code += "\n" + js;
    code +=
        "\n  <\/script>\n" +
        "<\/body>\n" +
        "</html>";
    document.getElementById("preview").setAttribute("srcdoc", code);
    }
        

改变页面上下布局

为方便改变编辑代码框和预览页面的大小占比,需要制作一个可拖拽来改变窗口大小的功能,通过监听鼠标按下、移动事件来动态改变上下两个模块的高度,具体实现方法如下:

<script>
    function $(id) {
        return document.getElementById(id);
    }
    window.onload = function() {
        var oBox = $("box"), oTop = $("top"), oBottom = $("bottom"), oLine = $("line");
        //鼠标按下移动时动态改变各个窗口的高度
        oLine.onmousedown = function(e) {
            var disY = (e || event).clientY;
            oLine.top = oLine.offsetTop;

            document.onmousemove = function(e) {
                var iT = oLine.top + ((e || event).clientY - disY);
                var e=e||window.event,tarnameb=e.target||e.srcElement;
                var maxT = oBox.clientHeight - oLine.clientHeight;
                oLine.style.margin = 0;
                iT < 0 && (iT = 0);
                iT > maxT && (iT = maxT);
                oLine.style.top = oTop.style.height = iT + "px";
                oBottom.style.height = oBox.clientHeight - iT + "px";
                //$("msg").innerText='top.width:'+oLine.style.height+'---bottom.height:'+oBottom.style.height+'---oLine.offsetHeight:'+oLine.offsetHeight+'---disY:'+disY+'---tarnameb:'+tarnameb.tagName;
                return false
            };
            //鼠标收起清空事件
            document.onmouseup = function() {
                document.onmousemove = null;
                document.onmouseup = null;
                oLine.releaseCapture && oLine.releaseCapture()
            };
            oLine.setCapture && oLine.setCapture();
            return false
        };
    };
</script>

以上便是实现一个简易版码上掘金的方法和思路,具体源码可查看:gitee.com/fcli/my-cod… 运行依赖node环境,可通过nginx代理使用。

总结

通过以上操作就能实现一个简易版码上掘金,文中涉及的ACE相关知识可到github.com/ajaxorg/ace 查看相关使用和配置。当然真正的在线代码编辑器比这复杂的多,如果觉得有用欢迎大家点赞加关注哦。

原文链接:https://juejin.cn/post/7351599129935249417 作者:叶落风尘

(0)
上一篇 2024年4月1日 下午4:53
下一篇 2024年4月1日 下午5:04

相关推荐

发表回复

登录后才能评论