【问题标题】:Svelte and Jquery - Dropdown.svelte:7 Uncaught TypeError: jquery(...).dropdown is not a functionSvelte 和 Jquery - Dropdown.svelte:7 Uncaught TypeError: jquery(...).dropdown is not a function
【发布时间】:2019-12-01 17:11:28
【问题描述】:

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

【问题讨论】:

    标签: jquery svelte svelte-3


    【解决方案1】:

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

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

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

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

    您的代码未能实现这一点的原因是,&lt;svelte:head&gt; 的内容仅在组件渲染时附加到 DOM,而不是之前。渲染后立即调用onMount,但是此时刚刚添加的&lt;script&gt;标签还没有加载完毕。

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

    那么,我们能做些什么呢?一种解决方案是在 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>
    
    ...
    

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

    【讨论】:

    • 感谢您的回答。遵循您的建议后,我没有收到原始错误。但是我现在遇到了一个不同的错误:Transition: Element is no longer attach to DOM。无法动画。我尝试解决此错误,但无法解决。
    • 您的代码似乎对我有用。我在this repo 的分支上推送了一个示例(注意:它不在master 上)。看看能不能帮上忙。另外,就像我说的,我不建议在 &lt;svelte:head&gt; 中添加 CSS,所以不要从我的仓库中复制它!
    猜你喜欢
    • 2021-04-26
    • 2017-08-01
    • 2016-07-07
    • 1970-01-01
    • 1970-01-01
    • 2014-09-09
    • 1970-01-01
    • 2020-12-18
    • 1970-01-01
    相关资源
    最近更新 更多