构建反应组件
我们都熟悉 dev.to 的“反应组件”(尽管我仍然不确定独角兽是用来做什么的!)这里有一个关于如何创建“反应组件”的简短教程——使用和不使用 JavaScipt。
让我们从 CSS 版本开始吧!
标记
我们将把每个反应包装在 中,并在 后<label>
添加<svg>
和一个空的:<span>
<input type="checkbox">
<label aria-label="React with heart">
<input type="checkbox" name="reaction-heart" value="75" style="--c:75" />
<svg></svg>
<span></span>
</label>
我们<input type="checkbox">
将使用 来控制state
和 value
。
图标
在 dev.to 上,当你对某事做出“反应”时,会使用两种不同的图标。“点赞”操作会显示一颗空心和一颗实心。“独角兽”和“书签”操作也是如此。
有人可能会说,只要稍微修改一下设计,图标就能直接切换 SVG 样式fill
,stroke
或者stroke-width
——但我们还是保留两个图标吧。我们会把<g>
它们组合到一个 SVG 中:
<svg viewBox="0 0 24 24">
<g><path d="M21.179 12.794l.013.014L12 22l-9.192-9.192.013-.014A6.5 6.5 0 0112 3.64a6.5 6.5 0 019.179 9.154zM4.575 5.383a4.5 4.5 0 000 6.364L12 19.172l7.425-7.425a4.5 4.5 0 10-6.364-6.364L8.818 9.626 7.404 8.21l3.162-3.162a4.5 4.5 0 00-5.99.334l-.001.001z"></path></g>
<g><path d="M2.821 12.794a6.5 6.5 0 017.413-10.24h-.002L5.99 6.798l1.414 1.414 4.242-4.242a6.5 6.5 0 019.193 9.192L12 22l-9.192-9.192.013-.014z"></path></g>
</svg>
在 CSS 中,我们可以使用:checked
伪选择器在两个图标之间切换(在<g>
标签中):
[name*="reaction-"]:checked + svg g:first-of-type,
[name*="reaction-"]:not(:checked) + svg g:last-of-type {
opacity: 0;
}
[name*="reaction-"]:checked + svg g:last-of-type {
opacity: 1;
}
太棒了,现在我们可以使用复选框在两个图标之间切换了,让我们添加一个计数器!你注意到style="--c:75"
标记里的 了吗?
我们将使用它作为 CSS 计数器:
counter-reset: reaction var(--c);
不幸的是,我们不能使用value
-attribute,如下所示:
counter-reset: reaction attr(value);
– 因此我们必须使用那个额外的自定义属性--c
作为初始值。
然后,我们再次挂接到:checked
-selector:
[name*="reaction-"]:checked {
counter-increment: reaction;
}
<span>
标记中的空白现在将发挥它的作用:
span::after {
content: counter(reaction);
}
但为什么是空的 <span>
?这是因为我们必须将计数器添加为伪元素内容(::before
或::after
)。
不幸的是,我们不能向中添加伪元素<input type="checkbox">
,因为<input>
-tags 是标签组的一部分,不能有子标签(又名“自闭合”标签)或伪内容(实际上它们可以在 Chrome 和 Safari 中,但这不是规范的一部分!)。
剩下的只是一些样式。以下是 Codepen 上纯 CSS 的示例:
JavaScript
虽然纯 CSS 版本很酷,但不太实用。你可能需要把响应存储在某个地方!
让我们从 CSS 中删除与计数器相关的内容,并style="--c"
从标记中删除 -part。我们将反应包装在一个 中<form id="react">
,并使用 -eventListener 监听更改onchange
:
react.addEventListener('change', (e) => {
const t = e.target;
t.parentNode.lastElementChild.innerText = t.value = t.value - 0 + (t.checked ? 1 : -1);
});
这个小片段将从当前反应中添加或减去 1
(一) ,然后将设置为该值。value
innerText
<span>
在此代码片段中,您可以添加fetch()
(带有POST
)来存储当前反应。
例如,在 dev.to 上,JSON
有一个 small -object POST
:
{
result: "create",
category: "like"
}
例如,使用 JavaScript:
如果要将所有元素的文本设置<span>
为value
s <input>
,请使用以下小代码片段来迭代elements
的集合<form>
:
[...react.elements].forEach(t => t.parentNode.lastElementChild.innerText = t.value);
就是这样!最近,dev.to 上有一个“星级评定”挑战(我的参赛作品是“使用单一输入和心情选择器进行星级评定”)。
观察其他开发人员如何解决问题总是很有趣的,所以如果您修改了我的示例,请在评论中分享链接,或者 - 甚至更好 - 制作您自己的“反应组件”!
文章来源:https://dev.to/madsstoumann/building-a-reaction-component-2noe