WEB编辑器哪家强

优采云 发布时间: 2022-05-06 18:30

  WEB编辑器哪家强

  

  作为一名coder,像VS Code这样的代码编辑器自然是必不可少的,你还可以使用类似CodeSandbox这样的online编辑器开发demo程序。编辑器更多是作为工具方便我们进行日常的代码开发工作,倘若将编辑器视作产品的一部分为其提供可扩展的能力,我们该如何应对。答案是:web编辑器,现在热门的可视化页面搭建系统便是一个典型的案例。

  今天要介绍的是三款开源的主流web编辑器:

  Ace

  CodeMirror

  Monaco Editor

  前世今生

  Ace是来自 Cloud9 Editor的一个独立的代码编辑器,它的前身是Bespin和后来的Skywriter。这两者最开始走的路线不一样,Bespin基于canvas,Ace基于DOM。Ace发布于2010年,之后Skywriter团队将Skywriter的插件系统和可扩展性融合到了Ace中,便形成了现在的Ace编辑器。现在,和Mozilla都在积极的开发和维护Ace。

  CodeMirror的第一版于2007年发布,该版本基于浏览器的contentEditable属性实现。2010年发布的Ace采用了新的技术并证明即使是使用javascript操作数以千行的DOM也不存在性能问题,这驱使了CodeMirror的重构并发布了第二个版本,弃用了之前的contentEditable,性能得到了很大提升。如今,CodeMirror即将发布最新的重构版本6。

  Monaco Editor算是后起之秀,随着2015年VS Code的发布而诞生,它与VS Code使用同样的核心代码。

  快速开始

  这里以不引入任何框架的,纯粹的html+css+js形式展示三类编辑器的使用。

  Ace

  官方示例

  <br /><br /><br /> <br /> <br /> Editor<br /> <br /> body {<br /> overflow: hidden;<br /> }<br /><br /> #editor {<br /> margin: 0;<br /> position: absolute;<br /> top: 0;<br /> bottom: 0;<br /> left: 0;<br /> right: 0;<br /> }<br /> <br /><br /><br /><br />function foo(items) {<br /> var i;<br /> for (i = 0; i &lt; items.length; i++) {<br /> alert("Ace Rocks " + items[i]);<br /> }<br />}

  复制代码

  这里承载编辑器内容的html标签是pre,实际开发中并不常见,可以替换成div。

  注意ace的引用方式。ace-builds repository是ace的最新发布包,直接将src* 子目录拷贝到项目中即可使用,发布包总共有四个版本。

  当然我们也可以自行打包,从github仓库拉取源码,执行下面的脚本。

  npm install<br />node ./Makefile.dryice.js<br />复制代码

  于是就得到了完整的版本,即上述四个版本中的第一个,还可以通过脚本选项生成另外三个版本或是指定输出目录。

  CodeMirror

  直接下载zip文件并拷贝到项目中即可使用。

  <br /><br /> <br /> <br /> <br /> <br /> Document<br /> <br /> <br /> <br /> <br /> .CodeMirror {<br /> border: 1px solid black;<br /> }<br /> <br /> <br /> <br /> <br /> <br /> <br /> <br /> <br /> // 方式1<br /> var ele = document.getElementById("editor");<br /> var editor = CodeMirror.fromTextArea(ele, {<br /> lineNumbers: true,<br /> mode: "javascript"<br /> });<br /> editor.setValue("var a = 'hello world';")<br /> // 方式2<br /> var editor2 = CodeMirror(document.getElementById("editor2"), {<br /> lineNumbers: true,<br /> value: "console.log('hello world');",<br /> mode: "javascript"<br /> })<br /> <br /> <br /><br />复制代码

  这里有两种方式创建编辑器,fromTextArea的方式具有一些额外的特性。详情戳这里

  Monaco Editor

  通过npm安装

  npm install monaco-editor<br />复制代码

  安装完成后生成三个版本。

  另外还有一个min版本的source maps文件夹和一个编辑器api描述文件monaco.d.ts

  AMD版本的官方示例

  <br /><br /> <br /> browser-amd-editor<br /> <br /> <br /> <br /> Monaco Editor Sample<br /> <br /><br /> <br /> <br /> <br /> require.config({ paths: { vs: "../node_modules/monaco-editor/min/vs" } });<br /><br /> require(["vs/editor/editor.main"], function () {<br /> var editor = monaco.editor.create(<br /> document.getElementById("container"),<br /> {<br /> value: [<br /> "function x() {",<br /> '\tconsole.log("Hello world!");',<br /> "}",<br /> ].join("\n"),<br /> language: "javascript",<br /> }<br /> );<br /> });<br /> <br /> <br /><br />复制代码

  实际项目基本都是基于前端框架开发,下面就以Vue为例介绍三类编辑器的使用。

  在Vue项目中的使用Ace

  npm install ace-builds<br />复制代码

  import ace from "ace-builds"<br />复制代码

  实际使用过程中我们一般都会指定代码的语言类型,还有可能修改编辑器的默认样式。这样的话,我们还需要引入相关的语言类型文件和主题文件。

  import "ace-builds/src-noconflict/mode-javascript.js"<br />import "ace-builds/src-noconflict/theme-tomorrow.js"<br />复制代码

  但是,如果我们想动态切换语言类型或是主题,是不是应该把对应的js文件全部引入呢?Ace为我们提供了更简洁的方法。

  import "ace-builds/webpack-resolver"<br />复制代码

  这样就完成了语言类型和主题的动态加载,前提是项目基于webpack构建的。

  设置主题

  myEditor.setTheme("ace/theme/tomorrow")<br />复制代码

  设置语言类型

  // 一个editor可能存在多个session<br />myEditor.session.setMode("ace/mode/javascript")<br />myEditor.setMode("ace/mode/javascript")<br />复制代码

  设置/获取值

  myEditor.setValue("the new text here")<br />myEditor.session.setValue("the new text here")<br />myEditor.getValue() // or session.getValue<br />复制代码

  设置tab大小

  myEditor.session.setTabSize(4)<br />复制代码

  是否只读

  myEditor.setReadOnly(true) // false可编辑<br />复制代码

  当我们要设置多个属性值时,除了单独调用每个api,还可以使用下面这种方式。

  myEditor.setOptions({<br /> mode: "ace/mode/javascript",<br /> theme: "ace/theme/tomorrow",<br /> value: "hello world"<br />})<br />复制代码

  有了这些常用的api,编辑器基本成型了。可以参考官网或是源码ace.d.ts查看全部的接口。

  Ace自带语法检查功能,目前支持JavaScript, JSON, PHP, CoffeeScript, CSS, XQuery,XML,HTML。

  效果如下:

  

  除了语法检查,还可以设置代码提示和自动补全。只需要引入语言构建扩展,并设置相关属性即可。

  import "ace-builds/src-noconflict/ext-language_tools"<br /><br />myEditor.setOptions({<br /> enableBasicAutocompletion: true,<br /> enableSnippets: true,<br /> enableLiveAutocompletion: true,<br />});<br />复制代码

  效果如下:

  

  图中的提示及补全片段都可以在源码中找到,我们可以按照源码中的语法添加自定义的提示及补全片段信息。

  CodeMirror

  npm install codemirror<br />复制代码

  import CodeMirror from "codemirror/lib/codemirror.js"<br />import "codemirror/lib/codemirror.css"<br />复制代码

  同样,对于主题和语言类型也需要引入相应的文件。

  import "codemirror/theme/material.css"<br />import "codemirror/mode/javascript/javascript.js"<br />复制代码

  设置属性

  myEditor.setOption("mode", "text/javascript")<br />myEditor.setOption("value", "hello world")<br />复制代码

  设置/获取值

  myEditor.getValue()<br />myEditor.setValue("hello world")<br />复制代码

  CodeMirror默认是没有语法检查功能的,需要利用插件addon进行扩展。

  import "codemirror/addon/lint/lint.css"<br />import "codemirror/addon/lint/lint.js"<br />import "codemirror/addon/lint/javascript-lint.js"<br />this.editor = CodeMirror.fromTextArea(this.$refs.editor, {<br /> mode: "text/javascript",<br /> gutters: ["CodeMirror-lint-markers"],<br /> lint: true<br />})<br />复制代码

  另外还需要引入语言对应的检查工具,可以在项目的index.html中引入。

  <br />复制代码

  效果如下。

  

  代码提示和智能补全,需要引入相关插件,设置属性并绑定快捷键触发。

  import "codemirror/addon/hint/show-hint.js"<br />import "codemirror/addon/hint/show-hint.css"<br />import "codemirror/addon/hint/javascript-hint.js"<br />myEditor = CodeMirror.fromTextArea(this.$refs.editor, {<br /> mode: "text/javascript",<br /> extraKeys: { "Ctrl-Enter": "autocomplete", "Cmd-Enter": "autocomplete" }<br />})<br />CodeMirror.commands.autocomplete = function (cm) {<br /> cm.showHint({ hint: CodeMirror.hint.javascript });<br />}<br />复制代码

  这里分别定义了windows和mac系统下触发代码提示和智能补全的组合键,Ctrl+Enter Cmd+Enter。效果如下。

  

  CodeMirror支持diff模式,需要引入的插件及实现如下。

  import "codemirror/addon/merge/merge.css"<br />import "codemirror/addon/merge/merge.js"<br /><br />const orig1 = `import Vue from 'vue'<br />import App from './App.vue'\n<br /><br />Vue.config.productionTip = false<br /><br />new Vue({<br /> render: h => h(App),<br />}).$mount('#app')`;<br /><br />const orig2 = `import Vue from "vue";<br />import Vuex from "vuex";<br />import App from "./App.vue";<br />import ElementUI from "element-ui";<br />import "element-ui/lib/theme-chalk/index.css";<br /><br />Vue.config.productionTip = false;<br /><br />Vue.use(ElementUI);<br />Vue.use(Vuex);<br /><br />const store = new Vuex.Store({<br /> state: {<br /> tabName: "",<br /> },<br /> mutations: {<br /> changeTab(state, tabName) {<br /> state.tabName = tabName;<br /> },<br /> },<br />});<br /><br />new Vue({<br /> render: (h) => h(App),<br /> store: store,<br />}).$mount("#app");`;<br /><br />myDiffEditor = CodeMirror.MergeView(<br /> document.getElementById("view"),<br /> {<br /> value: orig1,<br /> origLeft: null,<br /> orig: orig2,<br /> lineNumbers: true,<br /> mode: "text/javascript",<br /> highlightDifferences: true,<br /> connect: true,<br /> collapseIdentical: false<br /> }<br />);<br />复制代码

  diff功能需要依赖diff-match-patch开源库来计算差异。

  <br />复制代码

  最终效果如下。

  

  Monaco Editor

  npm install monaco-editor<br />复制代码

  此外,还需要安装配套的webpack插件。

  npm install monaco-editor-webpack-plugin<br />复制代码

  在vue.config.js中添加插件。

  const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');<br /><br />module.exports = {<br /> configureWebpack: {<br /> plugins: [<br /> new MonacoWebpackPlugin()<br /> ]<br /> }<br />}<br />复制代码

  import * as monaco from "monaco-editor"<br />复制代码

  设置语言类型

  const model = myEditor.getModel()<br />monaco.editor.setModelLanuage(model, "javascript")<br />复制代码

  设置主题

  monaco editor自带三种主题,默认的"vs"及"vs-dark"、"hc-black"。

  monaco.editor.setTheme("vs-dark")<br />复制代码

  设置属性

  例如,readOnly(是否只读)、renderLineHighlight(高亮行)、lineNumbers(是否显示行号)、fontSize(字体大小)等。

  myEditor.updateOptions({<br /> [name]: value // name表示属性名称,value为对应的属性值<br />})<br />复制代码

  这里仅列举了部分属性,完整的请参考官网或是源码monaco.d.ts。官网还提供了丰富的示例。

  monaco editor默认支持TypeScript, JavaScript, CSS, LESS, SCSS, JSON, HTML的语法校验及智能提示补全功能。效果如下。

  

  和桌面端的vscode没有任何区别。

  再看diff模式。

  const originalModel = monaco.editor.createModel(<br /> `import Vue from 'vue'<br />import App from './App.vue'\n<br /><br />Vue.config.productionTip = false<br /><br />new Vue({<br /> render: h => h(App),<br />}).$mount('#app')`,<br /> "javascript"<br /> );<br /> <br />const modifiedModel = monaco.editor.createModel(<br /> `import Vue from "vue";<br />import Vuex from "vuex";<br />import App from "./App.vue";<br />import ElementUI from "element-ui";<br />import "element-ui/lib/theme-chalk/index.css";<br /><br />Vue.config.productionTip = false;<br /><br />Vue.use(ElementUI);<br />Vue.use(Vuex);<br /><br />const store = new Vuex.Store({<br /> state: {<br /> tabName: "",<br /> },<br /> mutations: {<br /> changeTab(state, tabName) {<br /> state.tabName = tabName;<br /> },<br /> },<br />});<br /><br />new Vue({<br /> render: (h) => h(App),<br /> store: store,<br />}).$mount("#app");`,<br /> "javascript"<br /> );<br /> <br />myDiffEditor = monaco.editor.createDiffEditor(<br /> document.getElementById("monaco-editor")<br />);<br />myDiffEditor.setModel({<br /> original: originalModel,<br /> modified: modifiedModel,<br />});<br />复制代码

  效果如下。

  

  总结

  Ace,CodeMirror,Monaco Editor这三类编辑器的基本功能几乎相差无几,部分api高度相似,同样都具备部分语言的语法校验和代码智能提示及补全功能,只不过在实现方式上有所区别。自定义主题和语言,三者也都支持,实际项目遇到的可能性较小,文中没有介绍。Ace和CodeMirror的diff模式都依赖第三方开源库,而Monaco Editor自带diff功能。Monaco Editor与vscode同根同源,对于日常的vscode使用者,monaco editor相比之下无疑更加亲切,UI更加美观。CodeMirror重构之后的新版本同样值得期待。如果项目需要用到TypeScript,Ace和Monaco Editor可能是更好的选择。

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线