Динамически загружать компоненты vue из библиотеки CDN - PullRequest
0 голосов
/ 09 марта 2019

Я пытаюсь загружать внешние библиотеки динамически, используя vue. В этом случае эти библиотеки имеют vue компоненты, которые я хотел бы использовать. Моя текущая настройка следующая:

  1. Загрузка скриптов программно из CDN:
// The src CDN can change.
const src = 'https://cdn.jsdelivr.net/npm/vuetify/dist/vuetify.js';
const newScript = document.createElement('script');
newScript.src = src;
newScript.async = false;
newScript.type = 'text/javascript';
document.body.appendChild(newScript);
  1. Позже в коде я хотел бы использовать компонент динамически после завершения загрузки:
<component :is="dynamicComponent" v-bind="componentProperties">
   <!-- More things inside -->
</component>

где dynamicComponent - это свойство данных, которое можно изменить, и оно установлено как VBtn (пробовал также v-btn).

Однако этот подход не работает, поскольку компоненты еще не зарегистрированы в глобальном масштабе. Я получаю следующую ошибку: Unknown custom element: <VBtn>. Я также пытался сделать Vue.use(window.Veutify) после того, как window.Vuetify доступен, и проблема все еще существует.

Я также пытался дождаться доступности компонента с помощью

waitFor(() => Vue.options.components[dynamicComponent]).then(...)

однако он никогда не входит в функцию then. Интересно, что когда я помещаю Vue.options.components['VBtn'] в консоль, я возвращаю компонент обратно.

Я боролся с этим некоторое время. Будем весьма благодарны за любые предложения, документацию, ссылки или другие подходы, просто отметьте, что мне нужно полагаться на динамическую загрузку библиотек и динамическую загрузку их компонентов.

Заранее спасибо.

1 Ответ

0 голосов
/ 09 марта 2019

Вот важные шаги использования Vuetify, в следующем порядке:

  • нагрузка vuetify.min.css (обычно в <head>)
  • загрузить шрифт Material Icons (если вам это нужно)
  • нагрузка vue.js
  • нагрузка vuetify.js
  • инициализируйте ваше приложение.

Самое главное: и vue.js, и vuetify.js должны быть загружены перед инициализацией приложения.

<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify/dist/vuetify.min.css" rel="stylesheet">

<div id="app">
  <v-app>
    <v-content>
      <v-btn>Hello world</v-btn>
    </v-content>
  </v-app>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script type="application/javascript">
  Vue.config.devtools = false;
  Vue.config.productionTip = false;
</script>
<script src="https://cdn.jsdelivr.net/npm/vuetify/dist/vuetify.js"></script>
<script type="application/javascript">
  window.onload = new Vue({ el: '#app' });
</script>

Если вы действительно хотите / должны загружать свои скрипты динамически, вы можете заключить их в обещания, которые разрешают onload. Вот пример:

const loadScript = source => new Promise((resolve, reject) => {
  const script = document.createElement('script');
  script.src = source;
  script.type = 'text/javascript';
  script.onload = () => resolve();
  script.onerror = event => reject(`${event.target.src} failed to load. ¯\\_(ツ)_/¯`);
  document.body.appendChild(script);
});

Promise.all([
  loadScript('https://cdn.jsdelivr.net/npm/vue/dist/vue.js').then(() => {
    Vue.config.devtools = false;
    Vue.config.productionTip = false;
  }),
  loadScript('https://cdn.jsdelivr.net/npm/vuetify/dist/vuetify.js')
]).then(
  () => new Vue({ el: '#app' }), 
  error => console.log(error),
);
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify/dist/vuetify.min.css" rel="stylesheet">

<div id="app">
  <v-app>
    <v-content>
      <v-btn>Hello world</v-btn>
    </v-content>
  </v-app>
</div>
...