首页 > 解决方案 > 如何有效地在一页上有许多只读的摩纳哥差异视图?

问题描述

我的理解是,摩纳哥针对编辑进行了优化,一次只显示一个文件,具有固定大小的编辑器,它有自己的滚动条。

相反,我正在尝试构建一个页面,其中多个文件的差异位于彼此下方

我意识到这与摩纳哥的建造目的大相径庭,但最终似乎相同的视口和虚拟渲染技巧将适用,所以也许它是可能的?

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

一个非常难看的解决方法可能是拥有一个 Monaco 实例,连接所有文件,然后使用 ViewZones、自定义行号提供程序和代码折叠提供程序来实现多个文件的印象。这听起来很疯狂,还是真的可行?

还有其他建议吗?为什么 IStandaloneDiffEditor 名称中有独立?这是否意味着还有另一种方法可以创建许多更有效的差异编辑器?

标签: javascriptmonaco-editor

解决方案


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

您的问题的解决方案

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

引用您的问题: 为什么 IStandaloneDiffEditor 的名称中有独立?这是否意味着还有另一种方法可以创建许多更有效的差异编辑器?

从中一无所获。在维基百科中,我找到了独立意味着什么的答案:

独立软件可以指:

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

这意味着独立与单个实例无关,您可以拥有此编辑器的多个实例。但是您必须在计算机上拥有更多内存才能从该编辑器创建 100 个实例。这并不高效,因为您的内存中还有 100 个大 JavaScript 对象。

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

根据这个原则,在这种情况下,您可以使用下面我推荐的解决方案中的代码,并在后台仅从这个差异编辑器中删除一个实例。然后,您必须将所有 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;
    }
}

然后您必须从每个 editorOriginalPartHTML 和 editorModifiedPartHTML 中删除以下DOM对象:

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

以及您不能使用的所有其他对象。您可以在将editorOriginalPartHTML和添加editorModifiedPartHTML到您的DOM. 然后,您可以在每个div对象周围添加一个合适的对象width,heightstyle="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 加载文件内容。但是,如果您不明白如何加载它,请问我,我会写的。

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

在此处输入图像描述


推荐阅读