如何使用 Ace Editor 创建自定义 HTML 元素?
How to create a custom HTML element with Ace Editor?
我正在尝试使用将包含 Ace 编辑器实例的 Web 组件创建自定义 HTML 元素。我尝试的解决方案如下
customElements.define("test-editor", class extends HTMLElement {
constructor() {
super();
const editorContainer = document.createElement("div");
editorContainer.setAttribute("id", "editor_container");
const root = this.attachShadow({mode: "open"});
root.appendChild(editorContainer);
}
connectedCallback() {
ace.edit("editor_container");
}
});
然后我尝试在下面HTML中使用这个自定义元素(custom_element.js包含上面的内容)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<style>
html, body, #editor_container {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<test-editor></test-editor>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/ace.js"></script>
<script src="custom_element.js"></script>
</body>
</html>
当我在 Chrome 或 Firefox 中加载此页面时,我在控制台中收到以下错误
Uncaught Error: ace.edit can't find div #editor_container
at Object.t.edit (ace.js:1)
at HTMLElement.connectedCallback (custom_element.js:17)
at custom_element.js:3
有什么方法可以在自定义元素中嵌入 Ace Editor 的实例吗?
您已将阴影DOM附加到您的组件。
因为ACE Editor代码在页面中加载DOM(绿色),
它只能在页面 DOM(绿色)中找到 ACE 容器。
注意:您在第 DOM 页中也有 <style>
。这永远不会为元素 in shadowDOM.
设置样式
shadowDOM整个本质就是封装
参见:https://developers.google.com/web/fundamentals/web-components/shadowdom
您有 2 个选项可以使 ACE 编辑器在自定义元素中工作:
使用影子DOM,确实需要很多脚本。但是您可以在一个页面中获得多个编辑器。参见:https://raw.githack.com/ajaxorg/ace/master/demo/shadow-dom.html
不使用阴影DOM
(当我们这样做时,让元素加载所有依赖项):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script id=myEditor>
customElements.define("my-editor", class extends HTMLElement {
connectedCallback() {
const script = document.createElement("SCRIPT");
script.src = "//cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/ace.js";
script.onload = () => {
this.innerHTML = `<div id=editor_container>${myEditor.innerHTML}</div>`;
ace.edit("editor_container", {
mode: "ace/mode/javascript",
theme: "ace/theme/cobalt"
});
}
document.head.append(script);
}
});
</script>
<style>
html,
body,
#editor_container {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<my-editor></my-editor>
</body>
</html>
或在以下位置查看更多配置示例:
https://jsfiddle.net/CustomElementsExamples/p28mzu7g/
ace 存储库中有 a demo 使用 shadow-dom
重要的部分是将 dom 元素而不是字符串传递给编辑方法
并致电 editor.renderer.attachToShadowRoot
如果您正在寻找将编辑器添加到 Web 组件的最简单方法,Ace 团队确实提供了 api,只需构建一个编辑器,然后将其添加到影子 dom,例如这个:
aceEditor.renderer.attachToShadowRoot();
这是我为显示文件中的一段代码而构建的(它显示文件名和代码):
class CodeSnippet extends HTMLElement {
constructor(fileName, fileContents) {
super();
this._fileName = fileName;
this._fileContents = fileContents;
this.attachShadow({ mode: 'open' });
this.shadowRoot.appendChild(this.getTemplate());
}
getTemplate() {
const template = document.createElement('template');
template.innerHTML = `
<style>
.fileName {
color: gray;
}
</style>
<div class="fileName"></div>
<div class="codeSnippet"></div>`;
return template.content.cloneNode(true);
}
connectedCallback() {
//display the file name
const fileName = this.shadowRoot.querySelector('.fileName');
fileName.innerHTML = this._fileName;
//used to set the height of the ace editor (always have at least one line)
let numNewLines = 1;
//collect the newlines (null if there are none)
const allNewLines = this._fileContents.match(/\n/g);
if(allNewLines) {
//add an extra for the last line without a newline on it
numNewLines = allNewLines.length + 1;
}
//get the element where you want to add the editor
const codeSnippet = this.shadowRoot.querySelector('.codeSnippet');
//build an ace editor like normal
const aceEditor = ace.edit(codeSnippet, {
theme: "ace/theme/monokai",
mode: "ace/mode/java",
value: this._fileContents, //code to display
showPrintMargin: false,
readOnly: true,
fontSize: 16,
maxLines: numNewLines, //auto set the height of the editor
highlightActiveLine: false,
highlightGutterLine: false
});
//attach the ace editor to the shadow dom
aceEditor.renderer.attachToShadowRoot();
}
}
window.customElements.define('code-snippet', CodeSnippet);
不要忘记您需要在代码中的某处访问 Ace 库。我使用 CDN:
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/ace.js" type="text/javascript" charset="utf-8"></script>
要测试它,您可以将它们添加到另一个组件中:
const codeView = this.shadowRoot.querySelector('.codeView');
const snippet1 = new CodeSnippet('/testFile1.txt', 'line 1\nline 2\nline 3');
codeView.appendChild(snippet1);
const snippet2 = new CodeSnippet('/testFile2.txt', 'line 1\nline 2\nline 3\n');
codeView.appendChild(snippet2);
const snippet3 = new CodeSnippet('/testFile3.txt', '');
codeView.appendChild(snippet3);
我正在尝试使用将包含 Ace 编辑器实例的 Web 组件创建自定义 HTML 元素。我尝试的解决方案如下
customElements.define("test-editor", class extends HTMLElement {
constructor() {
super();
const editorContainer = document.createElement("div");
editorContainer.setAttribute("id", "editor_container");
const root = this.attachShadow({mode: "open"});
root.appendChild(editorContainer);
}
connectedCallback() {
ace.edit("editor_container");
}
});
然后我尝试在下面HTML中使用这个自定义元素(custom_element.js包含上面的内容)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<style>
html, body, #editor_container {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<test-editor></test-editor>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/ace.js"></script>
<script src="custom_element.js"></script>
</body>
</html>
当我在 Chrome 或 Firefox 中加载此页面时,我在控制台中收到以下错误
Uncaught Error: ace.edit can't find div #editor_container
at Object.t.edit (ace.js:1)
at HTMLElement.connectedCallback (custom_element.js:17)
at custom_element.js:3
有什么方法可以在自定义元素中嵌入 Ace Editor 的实例吗?
您已将阴影DOM附加到您的组件。
因为ACE Editor代码在页面中加载DOM(绿色),
它只能在页面 DOM(绿色)中找到 ACE 容器。
注意:您在第 DOM 页中也有 <style>
。这永远不会为元素 in shadowDOM.
设置样式
shadowDOM整个本质就是封装
参见:https://developers.google.com/web/fundamentals/web-components/shadowdom
您有 2 个选项可以使 ACE 编辑器在自定义元素中工作:
使用影子DOM,确实需要很多脚本。但是您可以在一个页面中获得多个编辑器。参见:https://raw.githack.com/ajaxorg/ace/master/demo/shadow-dom.html
不使用阴影DOM
(当我们这样做时,让元素加载所有依赖项):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script id=myEditor>
customElements.define("my-editor", class extends HTMLElement {
connectedCallback() {
const script = document.createElement("SCRIPT");
script.src = "//cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/ace.js";
script.onload = () => {
this.innerHTML = `<div id=editor_container>${myEditor.innerHTML}</div>`;
ace.edit("editor_container", {
mode: "ace/mode/javascript",
theme: "ace/theme/cobalt"
});
}
document.head.append(script);
}
});
</script>
<style>
html,
body,
#editor_container {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<my-editor></my-editor>
</body>
</html>
或在以下位置查看更多配置示例: https://jsfiddle.net/CustomElementsExamples/p28mzu7g/
ace 存储库中有 a demo 使用 shadow-dom
重要的部分是将 dom 元素而不是字符串传递给编辑方法 并致电 editor.renderer.attachToShadowRoot
如果您正在寻找将编辑器添加到 Web 组件的最简单方法,Ace 团队确实提供了 api,只需构建一个编辑器,然后将其添加到影子 dom,例如这个:
aceEditor.renderer.attachToShadowRoot();
这是我为显示文件中的一段代码而构建的(它显示文件名和代码):
class CodeSnippet extends HTMLElement {
constructor(fileName, fileContents) {
super();
this._fileName = fileName;
this._fileContents = fileContents;
this.attachShadow({ mode: 'open' });
this.shadowRoot.appendChild(this.getTemplate());
}
getTemplate() {
const template = document.createElement('template');
template.innerHTML = `
<style>
.fileName {
color: gray;
}
</style>
<div class="fileName"></div>
<div class="codeSnippet"></div>`;
return template.content.cloneNode(true);
}
connectedCallback() {
//display the file name
const fileName = this.shadowRoot.querySelector('.fileName');
fileName.innerHTML = this._fileName;
//used to set the height of the ace editor (always have at least one line)
let numNewLines = 1;
//collect the newlines (null if there are none)
const allNewLines = this._fileContents.match(/\n/g);
if(allNewLines) {
//add an extra for the last line without a newline on it
numNewLines = allNewLines.length + 1;
}
//get the element where you want to add the editor
const codeSnippet = this.shadowRoot.querySelector('.codeSnippet');
//build an ace editor like normal
const aceEditor = ace.edit(codeSnippet, {
theme: "ace/theme/monokai",
mode: "ace/mode/java",
value: this._fileContents, //code to display
showPrintMargin: false,
readOnly: true,
fontSize: 16,
maxLines: numNewLines, //auto set the height of the editor
highlightActiveLine: false,
highlightGutterLine: false
});
//attach the ace editor to the shadow dom
aceEditor.renderer.attachToShadowRoot();
}
}
window.customElements.define('code-snippet', CodeSnippet);
不要忘记您需要在代码中的某处访问 Ace 库。我使用 CDN:
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/ace.js" type="text/javascript" charset="utf-8"></script>
要测试它,您可以将它们添加到另一个组件中:
const codeView = this.shadowRoot.querySelector('.codeView');
const snippet1 = new CodeSnippet('/testFile1.txt', 'line 1\nline 2\nline 3');
codeView.appendChild(snippet1);
const snippet2 = new CodeSnippet('/testFile2.txt', 'line 1\nline 2\nline 3\n');
codeView.appendChild(snippet2);
const snippet3 = new CodeSnippet('/testFile3.txt', '');
codeView.appendChild(snippet3);