0

我正在尝试在 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>

在此处输入图像描述

4

1 回答 1

2

window.jQuery问题是 Semantic 的组件期望 jQuery在您加载其 JS 时已经可用。

例如,以下是摘录自dropdown.js(参见Github 上的行):

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

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

您的代码无法实现这一点的原因<svelte:head>是,只有在渲染组件时才会将 的内容附加到 DOM 中,而不是之前。在render之后立即onMount调用,但是<script>刚刚添加的标签此时还没有完成加载。

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

所以,我们能做些什么?一种解决方案是在您的捆绑包之前加载 jQuery index.html

    <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>

...

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

于 2019-12-01T09:11:28.460 回答