簡體   English   中英

Angular 在 index.html 中導入腳本並在組件中使用

[英]Angular import script in index.html and use it in component

我正在嘗試在 Angular 應用程序中使用Spotify SDK 我可以從 index.html 中的 CDN 導入腳本,但無法弄清楚我應該如何在組件級別實際使用它。 我覺得我在這里缺少一些基本的東西,比如以某種方式導入它,但我似乎無法得到任何工作。

我知道沒有太多信息可以解決,但實際上我只需要知道如何在組件級別使用導入的腳本。

嘗試在組件級別使用 SDK 時出現錯誤消息: Property 'onSpotifyWebPlaybackSDKReady' does not exist on type 'Window & typeof globalThis'

我還發現了這個源代碼,我想我可以嘗試作為一個例子來看看這一切是如何結合在一起的。 我不明白這一切是如何工作的,但在該項目的package.json中包含這一行: "@types/spotify-web-playback-sdk": "0.1.9",

原來@Konrad Linkowski 的評論和簡單地為所需對象聲明一個變量似乎可以解決這個問題並允許充分利用該庫。 可能有更正確的處理方式,但這沒有問題。

declare global {
  interface Window { onSpotifyWebPlaybackSDKReady: any; }
}
declare let Spotify: any;

window.onSpotifyWebPlaybackSDKReady = window.onSpotifyWebPlaybackSDKReady || {};

您可以將此代碼放入src文件夾中任何位置的后綴.d.ts的文件中。 我從這里獲取類型: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/spotify-web-playback-sdk/index.d.ts並將它們轉換為模塊。

spotify.d.ts

export {};

declare global {
  interface Window {
    onSpotifyWebPlaybackSDKReady(): void;
    Spotify: typeof Spotify;
  }

  namespace Spotify {
    interface Entity {
      name: string;
      uri: string;
      url: string;
    }

    interface Album {
      name: string;
      uri: string;
      images: Image[];
    }

    interface Error {
      message: string;
    }

    type ErrorTypes =
      | 'account_error'
      | 'authentication_error'
      | 'initialization_error'
      | 'playback_error';

    interface Image {
      height?: number | null | undefined;
      url: string;
      size?: string | null | undefined;
      width?: number | null | undefined;
    }

    interface PlaybackContextTrack extends Entity {
      artists: Entity[];
      content_type: string;
      estimated_duration: number;
      group: Entity;
      images: Image[];
      uid: string;
    }

    interface PlaybackContextRestrictions {
      pause: string[];
      resume: string[];
      seek: string[];
      skip_next: string[];
      skip_prev: string[];
      toggle_repeat_context: string[];
      toggle_repeat_track: string[];
      toggle_shuffle: string[];
      peek_next: string[];
      peek_prev: string[];
    }

    interface PlaybackContextMetadata extends Entity {
      current_item: PlaybackContextTrack;
      next_items: PlaybackContextTrack[];
      previous_items: PlaybackContextTrack[];
      restrictions: PlaybackContextRestrictions;
      options: {
        repeat_mode: string;
        shuffled: boolean;
      };
    }

    interface PlaybackContext {
      metadata: PlaybackContextMetadata | null;
      uri: string | null;
    }

    interface PlaybackDisallows {
      pausing?: boolean;
      peeking_next?: boolean;
      peeking_prev?: boolean;
      resuming?: boolean;
      seeking?: boolean;
      skipping_next?: boolean;
      skipping_prev?: boolean;
      toggling_repeat_context?: boolean;
      toggling_repeat_track?: boolean;
      toggling_shuffle?: boolean;
    }

    interface PlaybackRestrictions {
      disallow_pausing_reasons?: string[];
      disallow_peeking_next_reasons?: string[];
      disallow_peeking_prev_reasons?: string[];
      disallow_resuming_reasons?: string[];
      disallow_seeking_reasons?: string[];
      disallow_skipping_next_reasons?: string[];
      disallow_skipping_prev_reasons?: string[];
      disallow_toggling_repeat_context_reasons?: string[];
      disallow_toggling_repeat_track_reasons?: string[];
      disallow_toggling_shuffle_reasons?: string[];
    }

    interface PlaybackState {
      context: PlaybackContext;
      disallows: PlaybackDisallows;
      duration: number;
      paused: boolean;
      position: number;
      loading: boolean;
      timestamp: number;
      /**
       * 0: NO_REPEAT
       * 1: ONCE_REPEAT
       * 2: FULL_REPEAT
       */
      repeat_mode: 0 | 1 | 2;
      shuffle: boolean;
      restrictions: PlaybackRestrictions;
      track_window: PlaybackTrackWindow;
      playback_id: string;
      playback_quality: string;
      playback_features: {
        hifi_status: string;
      };
    }

    interface PlaybackTrackWindow {
      current_track: Track;
      previous_tracks: Track[];
      next_tracks: Track[];
    }

    interface PlayerInit {
      name: string;
      getOAuthToken(cb: (token: string) => void): void;
      volume?: number | undefined;
    }

    type ErrorListener = (err: Error) => void;
    type PlaybackInstanceListener = (inst: WebPlaybackInstance) => void;
    type PlaybackStateListener = (s: PlaybackState) => void;
    type EmptyListener = () => void;

    type AddListenerFn = ((
      event: 'ready' | 'not_ready',
      cb: PlaybackInstanceListener
    ) => void) &
      ((event: 'autoplay_failed', cb: EmptyListener) => void) &
      ((event: 'player_state_changed', cb: PlaybackStateListener) => void) &
      ((event: ErrorTypes, cb: ErrorListener) => void);

    class Player {
      readonly _options: PlayerInit & { id: string };
      constructor(options: PlayerInit);

      connect(): Promise<boolean>;
      disconnect(): void;
      getCurrentState(): Promise<PlaybackState | null>;
      getVolume(): Promise<number>;
      nextTrack(): Promise<void>;

      addListener: AddListenerFn;
      on: AddListenerFn;

      removeListener(
        event: 'ready' | 'not_ready' | 'player_state_changed' | ErrorTypes,
        cb?: ErrorListener | PlaybackInstanceListener | PlaybackStateListener
      ): void;

      pause(): Promise<void>;
      previousTrack(): Promise<void>;
      resume(): Promise<void>;
      seek(pos_ms: number): Promise<void>;
      setName(name: string): Promise<void>;
      setVolume(volume: number): Promise<void>;
      togglePlay(): Promise<void>;

      activateElement(): Promise<void>;
    }

    interface Track {
      album: Album;
      artists: Entity[];
      duration_ms: number;
      id: string | null;
      is_playable: boolean;
      name: string;
      uid: string;
      uri: string;
      media_type: 'audio' | 'video';
      type: 'track' | 'episode' | 'ad';
      track_type: 'audio' | 'video';
      linked_from: {
        uri: string | null;
        id: string | null;
      };
    }

    interface WebPlaybackInstance {
      device_id: string;
    }
  }
}

然后要使用它,您可以創建全局 window function,然后以編程方式添加腳本。

export class AppComponent {
  ngOnInit() {
    window.onSpotifyWebPlaybackSDKReady = () => {
      console.log('spotify script loaded');
      const player = new Spotify.Player({
        name: 'nameHere',
        getOAuthToken: () => {
          'functionHere';
        },
      });
      player.connect().then((success) => console.log('Connected:', success));
    };
    const script = document.createElement('script');
    script.src = 'https://sdk.scdn.co/spotify-player.js';
    document.body.appendChild(script);
  }
}

或者,您可以安裝此 package: https://www.npmjs.com/package/@types/spotify-web-playback-sdk

npm i @types/spotify-web-playback-sdk

但它沒有設置為模塊,因此您需要像這樣手動引用它

///  <reference types="@types/spotify-web-playback-sdk"/>

import { Component } from '@angular/core';

@Component({ ... })
export class AppComponent { ... }

這是用於引用類型的特殊 typescript 語法: https://www.typescriptlang.org/docs/handbook/triple-slash-directives.html#-reference-types-

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM