Somnia 组件编写指南
Without further ado
Somnia 组件编写指南
一个常见的 shortcode ,处理 js 在 Swup.js 切换后自动加载的问题。
<div x-data="test()" x-text="some"></div>
<script>
function test() {
return {
some: "test"
}
}
</script>html
这段代码出现在 shortcode 后。Swup.js 下的页面,切换页面时不会自动加载其中的 js ,导致 Alpine.js 初始化失败。
简码编写简化
一切为了更方便的编写简码!
方法 1 手动移动到 x-data
将函数 return 移动到 x-data 里。如 x-data="{ some: 'test' }"
方法 2 手动移动到 custom.js
将函数移动到 assets/js/custom.js
方法 3 移动到 head 触发后初始化
在 shortcode 中使用 x-load="event (somnia:moved)" 或者 x-load="idle",或者 x-ingore 延迟 Alpine.js 初始化。然后编写代码,在 Swup.js 事件触发后,再初始化。
<div x-data="test()" x-text="some" x-load="event (somnia:moved)"></div>
<script>
console.log("test loaded")
function test() {
return {
some: "test"
}
}
</script>html
assets/js/custom.js 中的函数 Somnia.prototype.swupPageInitCustom 函数加上
// 获取目标容器内的所有脚本元素 遍历每个脚本并将其移动到 head 中
scriptdocument.querySelectorAll('#content-wrapper script')s.forEach(script => {
const newScript = document.createElement('script');
newScript.innerHTML = script.innerHTML;
// 将脚本元素重新插入到 head 标签内
document.head.appendChild(newScript);
});
document.dispatchEvent(new CustomEvent('somnia:moved', { bubbles: true }));js
需要注意的是,这段代码比较粗糙,会导致多次加载多次触发,head 部分堆积重复。
方法 4 移动到 x-data 触发后初始化
使用 x-ingore 延迟 Alpine.js 初始化。移动相邻脚本内容到 x-data 中,替换元素触发初始化。
assets/js/custom.js 中的函数 Somnia.prototype.swupPageInitCustom 函数加上
document.querySelectorAll('div[x-ignore]').forEach(div => {
// 获取下一个相邻元素(即紧随其后的兄弟元素)
const nextElement = div.nextElementSibling;
// 如果相邻元素存在并且是脚本
if (nextElement && nextElement.tagName.toLowerCase() === 'script') {
// 将 innerText 设置到当前 div 的 x-data 属性上
div.setAttribute('x-data', nextElement.innerText);
nextElement.remove();
div.removeAttribute('x-ignore'); // 移除 x-ignore 属性
div.parentNode.replaceChild(div, div); // 触发 Alpine.js 重新解析 x-data
}
});js
这种方法脚本保留一个 object 或者函数都可。
<div x-data="test()" x-text="some" x-ignore></div>
<script>
function test() {
return {
some: "test"
}
}
</script>html
方法 5 Async Alpine 异步加载
函数移动到单独的 js 文件,async-alpine 异步加载。参考 Somnia/static/js/comment.mjs