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

简易版代码编辑预览功能

前言

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

介绍

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

页面结构

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

xml 复制代码
<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

swift 复制代码
<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)来将我们自定义的代码渲染到预览窗口上。

swift 复制代码
<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);
    }
        

改变页面上下布局

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

ini 复制代码
<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 查看相关使用和配置。当然真正的在线代码编辑器比这复杂的多,如果觉得有用欢迎大家点赞加关注哦。

相关推荐
PyAIGCMaster14 分钟前
python环境中,敏感数据的存储与读取问题解决方案
服务器·前端·python
baozhengw16 分钟前
UniAPP快速入门教程(一)
前端·uni-app
nameofworld25 分钟前
前端面试笔试(二)
前端·javascript·面试·学习方法·数组去重
帅比九日1 小时前
【HarmonyOS NEXT】实战——登录页面
前端·学习·华为·harmonyos
摇光931 小时前
promise
前端·面试·promise
麻花20131 小时前
WPF学习之路,控件的只读、是否可以、是否可见属性控制
服务器·前端·学习
.5481 小时前
提取双栏pdf的文字时 输出文件顺序混乱
前端·pdf
jyl_sh1 小时前
WebKit(适用2024年11月份版本)
前端·浏览器·客户端·webkit
狼叔2 小时前
前端潮流KK:科技达人与多面手,如何找到自己的乐趣?-浪说回顾
前端
zhanghaisong_20152 小时前
Caused by: org.attoparser.ParseException:
前端·javascript·html·thymeleaf