如何在一页上有效地拥有许多只读的Monaco Diff视图?

时间:2018-07-27 22:31:36

标签: javascript monaco-editor

我的理解是,摩纳哥使用固定大小的编辑器(具有自己的滚动条)进行了优化,可以一次显示一个文件。

相反,我正在尝试构建一个页面,其中多个文件的差异互不相同

  • 允许显示/隐藏每个文件,最多约100个文件
  • 隐藏文件中未更改的部分(并根据需要将其显示为上下文)
  • 每个文件没有一个滚动条,但整个页面都有一个滚动条
  • 这些文件通常只能查看,但一次只能支持一个文件的编辑

我意识到这与摩纳哥的设计大相径庭,但最终似乎似乎会应用相同的视口和虚拟渲染技巧,所以也许有可能吗?

我尝试为每个文件创建一个Monaco实例,但是大约30个实例开始变得缓慢。

一个非常丑陋的解决方法可能是只有一个Monaco实例,合并所有文件,然后与ViewZones,自定义行号提供程序和代码折叠提供程序一起使用,以获得多个文件的印象。这听起来听起来像疯了一样,还是真的可以奏效?

还有其他建议吗?为什么IStandaloneDiffEditor的名称中具有 standalone ?这是否意味着还有另一种方法来创建许多比较编辑器,效率更高?

1 个答案:

答案 0 :(得分:6)

  

引用您的问题:   我尝试为每个文件创建一个Monaco实例,但是大约30个实例开始变得缓慢。

您问题的解决方案

正如您所提到的,性能低迷。这是因为您的服务器或客户端可能没有足够的内存。您必须向服务器添加更多内存,或者可能要向客户端添加更多内存以提高性能。因为我没有足够的信息,所以我不能说它是服务器还是客户端。但是这种方法效率不高。

  

引用您的问题:   为什么IStandaloneDiffEditor的名称中具有独立名称?这是否意味着还有另一种方式来创建许多比较编辑器,效率更高?

一无所有。 In Wikipedia我找到了答案 standalone 的意思:

  

独立软件可以指:

     
      
  • 可以脱机运行的计算机软件,即不一定需要网络连接才能运行。
  •   
  • 不属于某些捆绑软件的软件。
  •   
  • 作为单独的计算机进程而不是现有进程的附件运行的程序。
  •   
  • 独立程序,不需要操作系统服务即可运行的程序。
  •   
  • 便携式应用程序,无需安装过程即可运行。
  •   

这意味着 standalone 与单个实例无关,并且您可以具有此编辑器的多个实例。但是您必须在计算机上拥有更多内存才能通过此编辑器创建100个实例。而且这样做效率不高,因为您的内存中还包含100个大的JavaScript对象。

在用于显示更改文件之间差异的其他服务上,它们仅使用DOM个对象或使用DOM对象+一个来自创建该对象的大型JavaScript对象的大实例,而不是其他100个大对象来自大型JavaScript对象的实例。

在这种情况下,根据本原则,您可以使用以下推荐的解决方案中的代码,并在后台仅从此差异编辑器中选择一个实例。然后,您必须将所有100个文件一个接一个地放置到此实例,并分别从一个文件中复制以下DOM对象:

  • <div class="editor original showUnused" ...
  • <div class="editor modified showUnused" ...

例如,您可以使用以下代码进行操作:

var diffPartContainars = document.querySelector('#container').querySelectorAll('.showUnused'),
    editorOriginalPartHTML,
    editorModifiedPartHTML;

for(var i = diffPartContainars.length; i--;)
{
    var obj = diffPartContainars[i],
        cln = obj.className;

    if(cln.indexOf('editor original') > -1)
    {
        obj.removeAttribute('style');
        editorOriginalPartHTML = obj.outerHTML;
    }
    if(cln.indexOf('editor modified') > -1)
    {
        obj.removeAttribute('style');
        editorModifiedPartHTML = obj.outerHTML;
    }
}

然后,您必须从DOM对象之后的每个editorOriginalPartHTML和editorModifiedPartHTML中删除:

  • <div class="invisible scrollbar horizontal" ...
  • <canvas class="decorationsOverviewRuler" ...
  • <div class="visible scrollbar vertical" ...

和所有其他无法使用的对象。当您将editorOriginalPartHTMLeditorModifiedPartHTML添加到DOM时,可以执行此操作。然后,您可以从每个对象中添加一个div对象,并带有合适的widthheightstyle="overflow:auto"。而且您可以做更多的事情:对于每个div对象,您可以添加一个onclickonmouseover侦听器,然后用差异编辑器实例替换此div对象视图

我认为这只是提高效率的一种方法。祝你好运!

推荐的高效解决方案

一种快速,便捷和高效的方法,只需单击以下文件名,即可仅拥有该编辑器的一个实例并加载新的源。

var diffEditor = null;
var filesContent =
{
    'SomeJavaScriptFile.js':
    {
        originalContent: 'alert("heLLo world!")',
        modifiedContent: 'alert("hello everyone!")',
        type: 'text/javascript'
    },
    'AnotherJavaScriptFile.js':
    {
        originalContent: 'function open(str)\n{\n\talert(str)\n}',
        modifiedContent: 'function output(value)\n{\n\tconsole.log(value)\n}',
        type: 'text/javascript'
    }
};

document.querySelector('#files').addEventListener('change', function(e)
{
    var fileName = this.options[this.selectedIndex].text,
        file = filesContent[fileName];

    openInDiffEditor(file);
});

function openInDiffEditor(file)
{
    if(!diffEditor)
        diffEditor = monaco.editor.createDiffEditor(document.querySelector('#container'));

    diffEditor.setModel({
        original: monaco.editor.createModel(file.originalContent, file.type),
        modified: monaco.editor.createModel(file.modifiedContent, file.type)
    });
}

//open the first file in select list:
var firstFileName = document.querySelector('#files').options[0].text;
openInDiffEditor(filesContent[firstFileName]);
<p>Please select one file on the left list to see the file differences after changes.</p>
<select id="files" size="3">
    <option selected>SomeJavaScriptFile.js</option>
    <option>AnotherJavaScriptFile.js</option>
</select>

<div id="container" style="height:100%;"></div>

文件内容必须通过AJAX加载。但是,如果您不知道如何加载它,请问我,我会写它。

此推荐解决方案的屏幕截图

enter image description here