简而言之,我正在努力实现的是创建一个可重用的 Alpine 组件,其子组件在 Django 模板片段中定义。
我有这个模板结构:
cities_page.html
(模板)/city.html
(片段)/carousel.html
(片段+Alpine)/carousel_item.html
(片段)。
cities_page
渲染许多 cities
,每个 carousel
渲染许多 carousel_items
。所有渲染都发生在服务器端。
cities_page.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Cities Page</title>
<script defer src="https://cdn.jsdelivr.net/npm/[email protected]/dist/cdn.min.js"></script>
</head>
<body>
{% for city in cities %}
{% include "myapp/snippets/city.html" with city=city %}
{% endfor %}
</body>
</html>
city.html
<div>
<h2>{{ city.name }}</h2>
{% include "myapp/snippets/carousel.html" with images=city.images %}
</div>
carousel.html
<div x-data="carousel">
<template x-for="item in items" :key="item">
<div x-html="item.itemHtml"></div>
</template>
</div>
<script>
document.addEventListener('alpine:init', () => {
Alpine.data(`carousel`, () => ({
items: [
{% for image in images %}
{
itemHtml: `{% include "myapp/snippets/carousel_item.html" with image=image %}`,
},
{% endfor %}
]
}));
});
</script>
carousel_item.html
<p>
Item: {{ image }}
</p>
views.py
def cities_page(request):
context = {
"cities": [
{
"name": "London",
"images": ["london1.jpg", "london2.jpg", "london3.jpg"]
},
{
"name": "Paris",
"images": ["paris1.jpg", "paris2.jpg", "paris3.jpg"]
},
]
}
return render(request, "myapp/cities_page.html", context=context)
我希望 Alpine 管理我的轮播项目的原因是我想设计操纵这些项目的交互。这可以是像
reverseOrder
和 removeItem
这样的方法。
这样做的结果是:
项目:paris1.jpg
项目:paris2.jpg
项目:paris3.jpg
项目:paris1.jpg
项目:paris2.jpg
项目:paris3.jpg
请注意,伦敦有巴黎的图像。问题是为巴黎轮播定义的脚本覆盖了为伦敦定义的脚本。
我解决这个问题的最佳尝试是像这样重写轮播
<div>
<template x-for="item in items" :key="item">
<div x-html="item.itemHtml"></div>
</template>
</div>
<script>
(() => {
const genRanHex = size => [...Array(size)].map(() => Math.floor(Math.random() * 16).toString(16)).join('');
const id = genRanHex(5)
const currentScript = document.currentScript;
const previousElement = currentScript.previousElementSibling;
previousElement.setAttribute("x-data", `carousel${id}`)
document.addEventListener('alpine:init', () => {
Alpine.data(`carousel${id}`, () => ({
items: [
{% for image in images %}
{
itemHtml: `{% include "myapp/snippets/carousel_item.html" with image=image %}`,
},
{% endfor %}
]
}));
});
})();
</script>
请注意,我
x-data
x-data
这感觉像是一种构建可重用组件的非常古怪的方法。
因此,我的问题是:编写此类组件的最佳实践是什么?我是否在 Alpine 上把事情推得太远了,我是否应该考虑使用 Vue/React 之类的东西来实现这样的功能?
感谢您提供任何帮助或分享任何相关资源。
我这里也有类似的东西。它可能有也可能没有太大帮助。
https://github.com/tochy97/djangoAPI
我正在使用加载器根据路径需要调用每个 Js 内容。
https://github.com/tochy97/djangoAPI/blob/main/static/components/common/js/loader.js
index.js 充当一切的初始化程序。
https://github.com/tochy97/djangoAPI/blob/main/static/components/common/js/index.js