Svelte and Jquery - Dropdown.svelte:7 Uncaught TypeError: jquery(...).dropdown is not a function

Svelte and Jquery - Dropdown.svelte:7 Uncaught TypeError: jquery(...).dropdown is not a function

我正在尝试在 Svelte 中使用语义 UI(使用 jQuery)。我正在尝试初始化下拉功能,但出现以下错误:Uncaught TypeError: jquery(...).dropdown is not a function。我不确定为什么会这样。

Dropdown.svelte

  <svelte:head>
       <script src="jquery.js"></script>
       <script src="dropdown.js"></script>
       <link rel="stylesheet" type="text/css" href="dropdown.css">
   </svelte:head>

   <script>
      import { onMount } from 'svelte';
      import jQ from 'jquery';

      onMount(() => {
        jQ( document ).ready(function() {
        jQ('.ui.selection.dropdown').dropdown();
      });   
     });

  </script>

  <div class="ui selection dropdown">
     <input type="hidden" name="gender">
     <i class="dropdown icon"></i>
     <div class="default text">Gender</div>
         <div class="menu">
            <div class="item" data-value="1">Male</div>
            <div class="item" data-value="0">Female</div>
         </div>
     </div>

问题是当您加载它们的 JS 时,Semantic 的组件期望 jQuery 已经作为 window.jQuery 可用。

例如,这是来自 dropdown.js 的摘录(参见 Github 上的 the line):

;(function ($, window, document, undefined) {
...
})( jQuery, window, document );

因此,在加载 Semantic 的 JS 之前,您必须确保 jQuery 已加载并附加到 window

您的代码无法实现此目的的原因是 <svelte:head> 的内容仅在呈现组件时附加到 DOM,而不是之前。 render后立即调用了onMount,但是此时刚刚添加的<script>标签还没有加载完毕

您可以通过侦听此脚本的 load 事件来进行同步,但这很复杂,不会让您走得太远。问题是这些 <svelte:head> 的内容被附加 组件的每个实例 。这不适用于可以在页面上多次出现的组件。

那么,我们能做什么呢?一种解决方案是在 index.html:

中的捆绑包之前加载 jQuery
    <script src="/vendor/jquery.js"></script>

    <script type="module" defer src='/build/bundle.js'></script>

有了这个,你可以保证 jQuery 在你的包代码执行之前可用。在你的 Dropdown.svelte 中,你会有这样的代码:

<script>
  import { onMount } from 'svelte'
  import '../semantic/dist/components/transition.js'
  import '../semantic/dist/components/dropdown.js'

  // you should also probably make your bundler process & manage your
  // CSS dependencies, because in <svelte:head>, CSS links could be
  // duplicated at runtime -- you'll need a Rollup / Webpack CSS plugin
  import '../semantic/dist/components/reset.css'
  import '../semantic/dist/components/transition.css'
  import '../semantic/dist/components/dropdown.css'

  onMount(() => {
    jQuery('.ui.selection.dropdown').dropdown()
  })
</script>

...

另一种选择是同步导入。对于正常的 ES 导入,您无法保证它们的处理顺序。但是您可以使用动态导入来做到这一点。这会给你这样的代码:

<script>
  import { onMount } from 'svelte'
  import jQuery from 'jquery'

  // import the required CSS, somehow

  onMount(async () => {
    if (!window.jQuery) window.jQuery = jQuery
    await import('../semantic/dist/components/transition.js')
    await import('../semantic/dist/components/dropdown.js')
    jQuery('.ui.selection.dropdown').dropdown()
  })
</script>

...

不过,您需要使您的捆绑器配置恰到好处才能在您的项目中启用动态导入。