在 Angular 自定义元素中传递外部属性或输入

Passing external attribute or Input in an Angular Custom Element

我正在尝试在 angular 自定义元素标签中传递对象输入。自定义元素由一个 videojs 标签组成。元素未读取我在自定义元素标签中提供的输入。

这里的代码是我要转换成自定义元素的视频播放器组件。

import { Component, ElementRef, Input, On Destroy, OnInit, ViewChild,AfterViewInit, ViewEncapsulation } from '@angular/core';
import videojs from "video.js"

@Component({
  selector: 'app-video-player',
  templateUrl: './my-video-player.component.html',
  styleUrls: ['./my-video-player.component.scss'],
  encapsulation:ViewEncapsulation.Emulated
})
export class MyVideoPlayerComponent implements OnInit,OnDestroy,AfterViewInit {
  @ViewChild('myVideoPlayer',{static:true})
  myVideoPlayer:ElementRef


  @Input() options:{
    fluid:boolean,
    aspectRatio:string,
    autoplay:boolean,
    controls:boolean,
    // height:number,
    // width:number,
    sources:{
      src:string,
      type:string
    }[],
  }

  player:videojs.Player;

  constructor(
  ) { }

  ngAfterViewInit(){
  }
  
  ngOnInit() {
    this.player = videojs(this.myVideoPlayer.nativeElement, this.options, function onPlayerReady() {
      console.log('onPlayerReady', this);
    });    
  }

  ngOnDestroy() {
    
  }

}


这是视频播放器组件HTML


<video id="video-js" preload="none" class="video-js vjs-default-skin" controls #myVideoPlayer></video>


这是我将 MyVideoPlayerComponent 转换为自定义元素的 appModule 代码。

import { BrowserModule } from '@angular/platform-browser';
import { CUSTOM_ELEMENTS_SCHEMA, DoBootstrap, Injector, NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { MyVideoPlayerComponent } from './my-video-player/my-video-player.component';
import { createCustomElement } from '@angular/elements';

@NgModule({
  declarations: [
    MyVideoPlayerComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
  ],
  providers: [],
  schemas:[CUSTOM_ELEMENTS_SCHEMA],
  bootstrap: [AppComponent],
  entryComponents:[MyVideoPlayerComponent]
})

export class AppModule implements DoBootstrap {
  constructor(private injector:Injector){

    const webComponent=createCustomElement(MyVideoPlayerComponent,{injector:this.injector});
    
    customElements.define('custom-player',webComponent)

  }

  

  ngDoBootstrap(){}
 }


在构建项目之后,或者即使我直接使用我在同一个 angular 项目中制作的内部测试组件。它显示视频播放器组件但不播放视频,因为即使我提供了属性它也无法读取源代码。

下面显示的代码说明了我如何尝试将输入提供给自定义元素。

<custom-player options="{ autoplay: true, controls: true, sources: [{ src: '../../assets/video.mp4', type: 'video/mp4' }]}" ></custom-player>


如果您能研究这个问题,我们将不胜感激。

这是我声明的自定义元素的给定屏幕截图。

红色标记表示它正在拾取 src,而突出显示的标记表示它没有将 src 放在视频标签中。

enter image description here

从资产开始时,您不需要 ../../(这通常是配置的有效起点)。

此外,您想将 <custom-player options= 更改为 <custom-player [options]=(如果没有 [],您实际上传入的是字符串,而不是对象)。

我想你遵循了一些像 this 这样的教程。如果上述没有效果,请尝试与该示例进行比较,看看是否还有其他相关差异。

编辑:
属性 绑定的一个非常简单的例子:

// interface for options

export interface VideoOptions {
  fluid?: boolean;
  aspectRation?: string;
  autoplay?: boolean;
  controls?: boolean;
  sources?: Sources[];
}

export interface Source {
  src: string;
  type: string;
}

// ParentComponent ts

export class ParentComponent {
  options: VideoOptions = {
    autoplay: true, 
    controls: true, 
    sources: [{ src: 'assets/video.mp4', type: 'video/mp4' }]
  }
}

// ParentComponent html

<app-child-component [options]="options">
</app-child-component>

// ChildComponent ts
export class ChildComponent {
  @Input() options: VideoOptions;
}

// ChildComponent html
<div>
  {{options?.fluid}} <br>
  {{options?.aspectRatio}} <br>
  {{options?.controls}} <br>
  {{options?.autoplay}} <br>
  <ng-container *ngIf="options.sources">
    <div *ngFor="let source of options.sources">
      {{source.src}} --- {{source.type}}
    </div>
  </ng-container>
</div>

看起来你已经从你的评论中解决了这个问题,但只是为了让其他遇到同样问题的人清楚,这就是发生这种情况的原因。

当您将组件转换为 Angular 网络组件时,任何输入都将按此处所述进行映射:

https://angular.io/guide/elements#mapping

A custom element hosts an Angular component, providing a bridge between the data and logic defined in the component and standard DOM APIs. Component properties and logic maps directly into HTML attributes and the browser's event system.

The creation API parses the component looking for input properties, and defines corresponding attributes for the custom element. It transforms the property names to make them compatible with custom elements, which do not recognize case distinctions. The resulting attribute names use dash-separated lowercase. For example, for a component with @Input('myInputProp') inputProp, the corresponding custom element defines an attribute my-input-prop.

自定义元素仅托管 Angular,它本身不是 Angular 组件。要将数据传递到输入,您必须使用 Angular 在该元素上创建的属性,类似于您使用数据属性的方式。属性值是一个字符串,所以如果你想传入一个对象,你必须将它与JSON进行转换。