如何解决Zurb Foundation:当作为 ES 模块导入时,Slider 插件不会触发事件
我试图在我的网站上仅使用 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>
我错过了什么?以及如何修复?
解决方法
好的。我想我找到了导致事件问题的原因。
在发布问题时,foundation-sites
模块导入使用最新版本的 Zurb Foundation (v6.6.3),并且该版本是使用 jQuery v3.5.1 导入在内部编译的。可以通过跟踪 https://cdn.skypack.dev/foundation-sites 中的网址并检查代码来检查它。
但在问题的代码示例中,我使用 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。
因此,解决方案是坚持使用某些版本的模块,以便与 foundation-sites
模块的内部 jQuery 版本“匹配”。
替换这个:
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。
如果有人有同样的问题但不想“坚持”使用某些版本的 jQuery。
当 Foundation 包装元素时,它会向该元素添加 jQuery{version}{some-kind-of-timestamp}
属性。像这样:
Foundation 添加了两个名称以 jQuery3510
开头的属性。其中之一包含 events
属性。但是当我们使用从不同 ES 模块导入的另一个 jQuery 版本时,还有另一个带有 jQuery3600
的 events
。当我这样做时
$('#test-slider').on('moved.zf.slider',function () {
// Do something
});
moved.zf.slider
事件的注册进入 jQuery3600
,而不是进入 jQuery3510
。
所以这里的解决方案是使用来自 jQuery3510
的事件更新包含 events
的 jQuery3600
。我使用执行此操作的函数扩展 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
});
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。