Zurb Foundation:Slider 插件在作为 ES 模块导入时不会触发事件
Zurb Foundation: Slider plugin doesn't fire events when imported as ES module
我试图在我的网站上仅使用 ES 模块,目前 Zurb Foundation 存在问题。我使用 Skypack 导入 ES 模块并且不使用任何打包器。
当我在页面上放置一些经典的初始化代码时,来自滑块的事件按预期触发:
<!-- 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>
但是当我将上面的代码转换为 ES 模块时,滑块事件停止工作:
<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>
我错过了什么?以及如何解决?
具有问题代码的演示 Codepen 是 here!
好的。我想我找到了导致事件问题的原因。
在发布问题时,foundation-sites
模块导入使用了最新版本的 Zurb Foundation (v6.6.3),并且该版本是在内部使用 jQuery v3.5.1 导入编译的。可以通过 https://cdn.skypack.dev/foundation-sites 中的 url 并检查代码来检查它。
但在问题的代码示例中,我使用 import $ from 'https://cdn.skypack.dev/jquery?min'
导入最新的 jQuery 版本 (v3.6.0)
因为我导入了 jQuery v3.6.0 并且 Foundation 模块在内部使用了 jQuery v3.5.1,事件监听器被放置在 不同的范围 (某种)不同于 Slider 的范围或任何 Zurb Foundation UI 元素,如果我在这里错了,请修复我。
选项 1。
所以解决方案是坚持使用某些版本的模块以获得 'match' 内部 jQuery 版本的 foundation-sites
模块。
替换为:
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
有了这个:
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
选项 2。
以防有人遇到同样的问题但不想 'stick' 使用某些版本的 jQuery。
当 Foundation 包装元素时,它会向该元素添加 jQuery{version}{some-kind-of-timestamp}
属性。像这样:
基金会添加了名称以 jQuery3510
开头的两个属性。其中之一包含 events
属性。但是当我们使用从不同 ES 模块导入的另一个 jQuery 版本时,还有另一个 jQuery3600
和 events
。当我这样做时
$('#test-slider').on('moved.zf.slider', function () {
// Do something
});
moved.zf.slider
事件的注册进入 jQuery3600
,而不是应有的 jQuery3510
。
所以这里的解决方案是用来自 jQuery3600
的事件更新包含 events
的 jQuery3510
。我用执行此操作的函数扩展 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]);
});
};
然后这个:
$('#test-slider').on('moved.zf.slider', function () {
// Do something
});
可以简单地替换为:
$('#test-slider').mutatedOn('moved.zf.slider', function () {
// Do something
});
我试图在我的网站上仅使用 ES 模块,目前 Zurb Foundation 存在问题。我使用 Skypack 导入 ES 模块并且不使用任何打包器。
当我在页面上放置一些经典的初始化代码时,来自滑块的事件按预期触发:
<!-- 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>
但是当我将上面的代码转换为 ES 模块时,滑块事件停止工作:
<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>
我错过了什么?以及如何解决?
具有问题代码的演示 Codepen 是 here!
好的。我想我找到了导致事件问题的原因。
在发布问题时,foundation-sites
模块导入使用了最新版本的 Zurb Foundation (v6.6.3),并且该版本是在内部使用 jQuery v3.5.1 导入编译的。可以通过 https://cdn.skypack.dev/foundation-sites 中的 url 并检查代码来检查它。
但在问题的代码示例中,我使用 import $ from 'https://cdn.skypack.dev/jquery?min'
导入最新的 jQuery 版本 (v3.6.0)
因为我导入了 jQuery v3.6.0 并且 Foundation 模块在内部使用了 jQuery v3.5.1,事件监听器被放置在 不同的范围 (某种)不同于 Slider 的范围或任何 Zurb Foundation UI 元素,如果我在这里错了,请修复我。
选项 1。
所以解决方案是坚持使用某些版本的模块以获得 'match' 内部 jQuery 版本的 foundation-sites
模块。
替换为:
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
有了这个:
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
选项 2。
以防有人遇到同样的问题但不想 'stick' 使用某些版本的 jQuery。
当 Foundation 包装元素时,它会向该元素添加 jQuery{version}{some-kind-of-timestamp}
属性。像这样:
基金会添加了名称以 jQuery3510
开头的两个属性。其中之一包含 events
属性。但是当我们使用从不同 ES 模块导入的另一个 jQuery 版本时,还有另一个 jQuery3600
和 events
。当我这样做时
$('#test-slider').on('moved.zf.slider', function () {
// Do something
});
moved.zf.slider
事件的注册进入 jQuery3600
,而不是应有的 jQuery3510
。
所以这里的解决方案是用来自 jQuery3600
的事件更新包含 events
的 jQuery3510
。我用执行此操作的函数扩展 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]);
});
};
然后这个:
$('#test-slider').on('moved.zf.slider', function () {
// Do something
});
可以简单地替换为:
$('#test-slider').mutatedOn('moved.zf.slider', function () {
// Do something
});