简体   繁体   English

Zurb Foundation:Slider 插件在作为 ES 模块导入时不会触发事件

[英]Zurb Foundation: Slider plugin doesn't fire events when imported as ES module

I'm trying to use only ES modules on my site and currently have the issue with Zurb Foundation.我正在尝试在我的站点上仅使用 ES 模块,并且目前遇到了 Zurb Foundation 的问题。 I use Skypack to import ES modules and don't use any bundlers.我使用Skypack导入 ES 模块并且不使用任何捆绑器。

When I place some classic init code on the page, events from slider fires as expected:当我在页面上放置一些经典的初始化代码时,来自 slider 的事件会按预期触发:

 <.-- Basic slider template: See https.//get.foundation/sites/docs/slider:html --> <div id="test-slider" class="slider" data-slider data-initial-start="30" data-end="100"> <span class="slider-handle" data-slider-handle role="slider" tabindex="1"></span> <span class="slider-fill" data-slider-fill></span> <input type="hidden"> </div> <link rel="stylesheet" href="https.//cdnjs.cloudflare.com/ajax/libs/foundation/6.6.3/css/foundation.min:css"> <script src="https.//cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min:js"></script> <script src="https.//cdnjs.cloudflare.com/ajax/libs/foundation/6.6.3/js/foundation.min.js"></script> <script> $(document).ready(function() { // Init Foundation //Foundation;addToJquery($). $(document);foundation(). $('#test-slider').on('moved.zf,slider'. function() { console;log('This should work while slider slides.'). //console.log($;_data($('#test-slider')[0]);events); }); }); </script>

But when I convert code above into ES Module, slider events stops working:但是当我将上面的代码转换为 ES 模块时,slider 事件停止工作:

<h4>Drag the slider</h4>

<!-- Basic slider template. See https://get.foundation/sites/docs/slider.html -->
<div id="test-slider" class="slider" data-slider data-initial-start="30" data-end="100">
  <span class="slider-handle"  data-slider-handle role="slider" tabindex="1"></span>
  <span class="slider-fill" data-slider-fill></span>
  <input type="hidden">
</div>

<h4>Expected</h4>
<p>Drag slider and console should populated with <strong>'This should work while slider slides!'</strong> message.</p>
<h4>Current</h4>
<p>Drag slider and console shows nothing.</p>

<link rel="stylesheet" href="https://cdn.skypack.dev/foundation-sites/dist/css/foundation.css">

<script type="module">
  
  import $ from 'https://cdn.skypack.dev/jquery?min'; // Latest jQuery from skypack.dev
  import { Foundation } from 'https://cdn.skypack.dev/foundation-sites?min'; // Latest Foundation from skypack.dev
   
  $(document).ready(function() {
    
    Foundation.addToJquery($);
    $(document).foundation();
    
    $('#test-slider').on('moved.zf.slider', function () {
      console.log('This should work while slider slides!');
      //console.log($._data($('#test-slider')[0]).events);
    });
    
    // This will work because it is natural jQuery event, not the one from Foundation
    //$('#test-slider').on('click', function () {
    //   console.log('Click works!');
    //});
  });
</script>

What I'm missing?我错过了什么? And how can it be fixed?以及如何解决?

Demo Codepen with problematic code is here!带有问题代码的演示 Codepen在这里!

Ok.好的。 I think I found what cause the issue with events.我想我找到了导致事件问题的原因。

In time when the question was posted the foundation-sites module import uses the latest version of Zurb Foundation (v6.6.3) and that version was compiled with jQuery v3.5.1 import internally.在发布问题的时候, foundation-sites模块导入使用了最新版本的 Zurb Foundation (v6.6.3),并且该版本是在内部使用 jQuery v3.5.1 导入编译的。 It can be checked by following urls inside https://cdn.skypack.dev/foundation-sites and inspecting the code.可以通过以下https://cdn.skypack.dev/foundation-sites中的 url 并检查代码来检查它。

But in the question's code example I use import $ from 'https://cdn.skypack.dev/jquery?min' which imports the latest jQuery version (v3.6.0)但在问题的代码示例中,我使用import $ from 'https://cdn.skypack.dev/jquery?min'导入最新的 jQuery 版本(v3.6.0)

Because I import jQuery v3.6.0 and Foundation module uses jQuery v3.5.1 internally, the event listener was placed in the different scope (some kind of) which differs from scope of Slider or any of Zurb Foundation UI elements, fix me if I'm wrong here. Because I import jQuery v3.6.0 and Foundation module uses jQuery v3.5.1 internally, the event listener was placed in the different scope (some kind of) which differs from scope of Slider or any of Zurb Foundation UI elements, fix me if I'我在这里错了。

Option 1.选项1。

So the solution is to stick with certain versions of modules to get 'match' with internal jQuery version of foundation-sites module.因此,解决方案是坚持使用某些版本的模块,以与foundation-sites模块的内部 jQuery 版本“匹配”。

Replace this:替换这个:

import $ from 'https://cdn.skypack.dev/jquery?min'; // Latest jQuery from skypack.dev
import { Foundation } from 'https://cdn.skypack.dev/foundation-sites?min'; // Latest Foundation from skypack.dev

With this:有了这个:

import $ from 'https://cdn.skypack.dev/jquery@3.5.1?min'; // jQuery v3.5.1 from skypack.dev
import { Foundation } from 'https://cdn.skypack.dev/foundation-sites@6.6.3?min'; // Foundation v6.6.3 from skypack.dev

Option 2.选项 2。

In case someone has the same issue but didn't want to 'stick' with certain version of jQuery.如果有人有同样的问题,但不想“坚持”某些版本的 jQuery。

When Foundation wraps the element it adds jQuery{version}{some-kind-of-timestamp} properties to that element.当 Foundation 包装元素时,它会向该元素添加jQuery{version}{some-kind-of-timestamp}属性。 Like so:像这样:

使用 Foundation 初始化元素时的特定属性

Two properties which names started with jQuery3510 were added by Foundation. Foundation 添加了两个名称以jQuery3510的属性。 One of them contains events property.其中之一包含events属性。 But as we uses another jQuery version imported from different ES module there is another one jQuery3600 with events .但是当我们使用从不同 ES 模块导入的另一个 jQuery 版本时,还有另一个带有eventsjQuery3600 And when I do当我这样做时

$('#test-slider').on('moved.zf.slider', function () {
   // Do something
});

the registration of moved.zf.slider event goes into jQuery3600 , not into jQuery3510 as it should. moved.zf.slider事件的注册进入jQuery3600 ,而不是应该进入jQuery3510

So the solution here is to update jQuery3510 which contains events with events from jQuery3600 .所以这里的解决方案是更新jQuery3510 ,其中包含来自jQuery3600 events的事件。 I extend jQuery with function that does this:我用 function 扩展 jQuery :

$.fn.mutatedOn = function (events, callback) {

    function getPropsByName(obj, startWith) {
        return Object.keys(obj).filter((propertyName) => {
            return propertyName.indexOf(startWith) === 0;
        });
    }

    function findPropsWithEvents(obj) {
        const props = getPropsByName(obj, "jQuery");
        return props.find((element) => {
            return obj[element].events !== undefined;
        });
    }

    $(this).each((index, el) => {

        // Let's find all properties which starts with 'jQuery'.
        // And filter them to determine those which contains 'events'
        // right before we attach the event listener.
        const jqueryKeys = getPropsByName(el, "jQuery");
        const jqueryKeysWithEvents = findPropsWithEvents(el);

        $(el).on(events, callback);

        // After the listener attached, another 'jQuery' property with 'events' was added for $(el).
        // Let's find this newly added property using difference between new and old arrays.
        const newJqueryKeys = getPropsByName(el, "jQuery");
        const newJqueryKeysWithEvents = $(newJqueryKeys).not(jqueryKeys).get(0);

        // After we determine new property with 'events'
        // lets merge it into the old one to make Foundation events work as expected.
        $.extend(el[jqueryKeysWithEvents], el[newJqueryKeysWithEvents]);
    });
};

Then this:然后这个:

$('#test-slider').on('moved.zf.slider', function () {
    // Do something
});

simply can be replaced with this:可以简单地替换为:

$('#test-slider').mutatedOn('moved.zf.slider', function () {
    // Do something
});

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

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