简体   繁体   English

加载第三方库 javascript

[英]Loading a third-party javascript library

I developed a web radio player using Vue Cli.我使用 Vue Cli 开发了一个 web 广播播放器。 Now I have to add a new functionality using an external library (it's aimed to handle audio advertising) and this library must be served from the remote host .现在我必须使用外部库添加新功能(它旨在处理音频广告)并且必须从远程主机提供该库 I can't just download the library and import it locally.我不能只下载库并在本地导入它。

Setup设置

In my Vue App I have several components and in one of them I have an audio tag handling the radio playback.在我的 Vue 应用程序中,我有几个组件,在其中一个组件中,我有一个处理无线电播放的音频标签。 I need to detect the click on the play button, load the ad, play it and then go to the radio regular playback.我需要检测播放按钮的点击、加载广告、播放它然后 go 到收音机常规播放。

Approachs I tried我尝试过的方法

  1. Loading the external library in the index.html file.在 index.html 文件中加载外部库。 It works but I can't interact with the player being loaded in Vue.它有效,但我无法与 Vue 中加载的播放器进行交互。 For example, if I try to listen to the play event in the index.html file ( audio.addEventListener("play", onPlay); , I just receive "audio not defined" in the web console.例如,如果我尝试收听 index.html 文件中的播放事件 ( audio.addEventListener("play", onPlay); ,我只会在 web 控制台中收到“音频未定义”。
  2. Loading the external library in the mounted () section of my component:在我的组件的 mounted () 部分加载外部库:
const triton = document.createElement('script')
triton.setAttribute('src', '//sdk.listenlive.co/web/2.9/td-sdk.min.js')
document.head.appendChild(triton)
this.initPlayerSDK()
triton.onload = () => {
  let player = new TDSdk(this.tdPlayerConfig)
  console.log(player)
}

The problem with this approach is that after npm run serve I receive the message 'TDSdk' is not defined which makes complete sense.这种方法的问题是,在npm run serve后,我收到消息'TDSdk' is not defined ,这是完全合理的。 I'm loading the external JS file but webpack isn't interpreting its content because that it's done in runtime.我正在加载外部 JS 文件,但 webpack 没有解释其内容,因为它是在运行时完成的。 I have to add the external in my vue.config.js, but this doesn't work neither:我必须在我的 vue.config.js 中添加外部,但这也不起作用:

vue.config.js vue.config.js

const path = require('path')

module.exports = {
  publicPath: './',
  /*configureWebpack: {
    externals: {
      tdSdk: 'tdSdk'
    }
  },*/
  chainWebpack: config => {
    config.module
    .rule('images')
    .test(/\.(png|jpe?g|gif|webp)(\?.*)?$/)
    .use('url-loader')
    .loader('file-loader') // not url-loader but file-loader !
    .tap((options) => { // not .option() but .tap(options...)
      // modify the options...
      options.name = 'img/[name].[ext]'
      return options
    }),
    config.externals([
      {
        'tdSdk': 'TDSdk'
      },
    ])
  },
  css: {
    loaderOptions: {
      sass: {
        sassOptions: {
        includePaths: [path.resolve(__dirname, './node_modules/compass-mixins/lib')]
        }
      }
    }
  },
  externals: {
    tdSdk: 'TDSdk'
  }
}

myComponent.vue我的组件.vue

import tdSdk from 'tdSdk'

My solution was to load the library in the public/index.html file and then wait for the DOM being loaded so I could add the event listener to the audio element already loaded:我的解决方案是在 public/index.html 文件中加载库,然后等待加载 DOM,这样我就可以将事件监听器添加到已加载的音频元素中:

document.addEventListener('DOMContentLoaded', function() {
var playControl = document.getElementById('playIcon');
playControl.addEventListener("click", onPlay);
}

Then, in the Vuex store I needed to access the variables defined in the javascript located in the index.html.然后,在 Vuex 存储中,我需要访问位于 index.html 中的 javascript 中定义的变量。 To do that, I set the window.adState (the var I'm using) as a global var in my store file:为此,我在存储文件中将window.adState (我正在使用的变量)设置为全局变量:

Vuex.Store.prototype.$adState = window.adState

Finally, in my actions/mutations I used this.$adState to check its content:最后,在我的动作/突变中,我使用 this.$adState 检查它的内容:

playPause ({ commit, dispatch }) {
console.log('AdState', this.$adState)
(...)
}

Answer added on behalf of OP.代表 OP 添加的答案。

The import cannot be resolved at the time when the script is evaluated because TDSdk global is not available.由于TDSdk global 不可用,因此在评估脚本时无法解析导入。 A script that is dynamically added to head is loaded asynchronously so there will be race condition any way.动态添加到head的脚本是异步加载的,因此无论如何都会出现竞争条件。

<script> needs to be added dynamically if there's dynamic behaviour involved or like a condition or a developer doesn't have control over page layout. <script>如果涉及动态行为或类似条件或开发人员无法控制页面布局,则需要动态添加。 For static script, Vue CLI project's public index.html can be modified:对于static脚本,可以修改Vue CLI项目的public index.html

  <body>
    <div id="app"></div>
    <script src="//sdk.listenlive.co/web/2.9/td-sdk.min.js"></script>
    <!-- built files will be auto injected -->
  </body>

Application bundle is evaluated after the script and the global is expected to be available there.应用程序包在脚本之后进行评估,并且全局预计在那里可用。

Externals are commonly used for packages that were swapped to ones that were externally loaded, usually from CDN.外部通常用于交换到外部加载的包,通常来自 CDN。 Since tdSdk is not a real package and has no prospects to be swapped for one, it doesn't serve a good purpose to map it to a global and import it.由于tdSdk不是真正的 package 并且没有交换的前景,因此将它 map 到全球并导入它没有一个好的目的。 It can be just used as TDSdk global in the application.它可以在应用程序中作为TDSdk全局使用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM