Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/31.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 扩展自定义元素在角度2+;_Javascript_Angular - Fatal编程技术网

Javascript 扩展自定义元素在角度2+;

Javascript 扩展自定义元素在角度2+;,javascript,angular,Javascript,Angular,我无法让Angular(2+,而不是AngularJS)很好地处理扩展的自定义元素,它的定义如下: class FancyButton extends HTMLButtonElement { connectedCallback() { this.innerText = `I'm a fancy-button!`; this.style.backgroundColor = 'tomato'; } } customElements.define(

我无法让Angular(2+,而不是AngularJS)很好地处理扩展的自定义元素,它的定义如下:

  class FancyButton extends HTMLButtonElement {
    connectedCallback() {
      this.innerText = `I'm a fancy-button!`;
      this.style.backgroundColor = 'tomato';
    }
  }

  customElements.define("fancy-button", FancyButton, {
    extends: "button"
  });
<button is="fancy-button">Fancy button here</button>
这样使用:

  class FancyButton extends HTMLButtonElement {
    connectedCallback() {
      this.innerText = `I'm a fancy-button!`;
      this.style.backgroundColor = 'tomato';
    }
  }

  customElements.define("fancy-button", FancyButton, {
    extends: "button"
  });
<button is="fancy-button">Fancy button here</button>
这里的花式按钮
根据以下Google开发者资源,该定义完全符合web标准:

它在香草web设置和React中工作正常,但Angular忽略了它并显示了一个标准按钮,显然忽略了is=“fancy button”属性

下面是一个演示此操作的示例。 一个奇特的按钮位于角度范围(index.html)之外,工作正常。 另一个按钮位于角度范围(app.component.html)内,不起作用


为什么?为什么?

有两种类型的自定义元素

  • 自治自定义元素,它们是
    扩展HtmleElement的类

  • 自定义内置元素,这些元素是扩展 元素的特定类型,例如
    扩展HTMLButtoneElement

  • 角度(更多详细信息)中不支持自定义内置元素 关于这一点,请参见下文)。它们在Safari中仍然不受支持(截至 2020年9月: )

    您的示例是一个定制的内置元素。解决方法 我的工作就是将任何定制的内置元素重写为自治元素 围绕内置元素的自定义元素。这给了我 我想要的封装,它为我提供了一种定制内置的方法,它可以与Angular和Safari一起使用

    对于上面的示例,翻译为:

    class FancyButtonToo extends HTMLElement {
      connectedCallback() {
        const buttonElement = document.createElement('button');
        this.appendChild(buttonElement);
        buttonElement.innerText = "Fancy button #2 here!";
        buttonElement.style.backgroundColor = 'tomato';
      }
    }
    
    customElements.define("fancy-button-too", FancyButtonToo);
    
    (项目还需要
    模式:[自定义元素\u模式]
    已添加。) 至
    app.module.ts
    )。此处的完整代码:, 它的渲染方式如下(原始的“花式按钮”留作比较):

    附加信息 问:我们是否确定Angular不能支持定制的内置元素(如 反对,比如说,存在一些我们不知道的模糊配置)

    答:我们确信:规范文件 深入讨论自治自定义元素之间的差异 以及定制的内置元素。一个重要的区别在于 元素的程序化构造:

    // Built-in Elements and Autonomous Custom Elements are created like this:
    el = createElement(name);
    // examples
    el = createElement("button"); // normal built-in button
    el = createElement("fancy-text"); // a custom element
    
    // Customized Built-in Elements are created like this:
    el = createElement(built-in-name, { is: custom-built-in-name });
    // example
    el = createElement("button", { is: "fancy-button" });
    
    相关的角度模板渲染代码位于 对于Angular的当前版本,您将发现:

    class DefaultDomRenderer2 implements Renderer2 {
      /* ... */
      createElement(name: string, namespace?: string): any {
        if (namespace) {
          return document.createElementNS(NAMESPACE_URIS[namespace] || namespace, name);
        }
        return document.createElement(name);
      }
      /* ... */
    }
    
    角度渲染器当前没有额外的代码 需要将第二个参数传递到
    createElement()
    ;它不能 创建自定义内置元素。

    
    类DefaultDomRender2实现RenderR2{
    // ...
    创建(名称:字符串、名称空间或选项?:字符串|元素创建选项){
    if(名称空间选项和类型名称空间选项==='string'){
    //在Ivy(不是ViewEngine)提供实际名称空间的情况下,按键查找
    //将导致未定义,因此我们只在此处返回名称空间。
    return document.createElements(名称空间URI[名称空间或选项]| |名称空间或选项,名称);
    }
    if(namespaceorptions&&namespaceorptions.hasOwnProperty('is')){
    返回document.createElement(名称、命名空间或选项作为ElementCreationOptions);
    }
    返回文档.createElement(名称)
    }
    }
    
    我甚至不会走那条路。。。我们有指令只用于这样的情况:)我明白了。我这样做是为了框架不可知论,我认为“是”按钮“这种方法非常好。在React中工作完美,没有任何React特定代码。我没有在模板中使用标记。它在index.html文件中。不过,我明白你的意思,谢谢你的回答。如果您感兴趣,这个问题与相同的问题有关:您是否考虑过通过此改进向angular存储库发送贡献?您的建议创建(名称:string,namespaceOrOptions?:string | ElementCreationOptions){if(namespaceOrOptions&&typeof namespaceOrOptions==='string'){return document.createElements(NAMESPACE|URIS[namespaceOrOptions]| | namespaceOrOptions,name)}if(namespaceOrOptions&&namespaceOrOptions.hasOwnProperty('is')){return document.createElement(name,namespaceOrOptions as element CreationOptions)}return document.createElement(name)}是不是像约翰·C那样?