使用数据属性代替HTML类来表示状态
HTML类的问题
通常情况下,当在HTML中表示UI状态时,我们使用类。这通常会转化为React组件或JavaScript代码,根据一些条件来添加或删除类。让我们来看一个例子:
<div id="order">
<!-- 订单摘要内容 -->
</div>
const orderData = {
loading: false,
completed: false,
errorMessage: null
};
const order = document.querySelector('#order');
order.className = `order-summary
${orderData.completed ? 'completed' : ''}
${orderData.loading ? 'loading' : ''}
${orderData.errorMessage ? 'error' : ''}`;
在这个例子中,我们正在为订单摘要的元素建模。该元素可以处于三种状态之一:加载中,已完成_或_错误。我们使用类来表示这些状态,并使用JavaScript根据订单的状态添加或删除这些类。
从UI中确定订单的状态也应该很简单。我们只需检查元素上存在的类即可:
const order = document.querySelector('#order');
const isCompleted = order.getAttribute('data-state') === 'completed';
const isLoading = order.getAttribute('data-state') === 'loading';
const hasError = order.getAttribute('data-state') === 'error';
这种方式可能有点繁琐,但在JavaScript中处理DOM元素通常都是如此。让我们来看一下可以用来样式化这三种状态的一些CSS:
.order-summary.completed {
background-color: green;
}
.order-summary.loading {
background-color: yellow;
}
.order-summary.error {
background-color: red;
}
非常简单易懂。然而,如果由于某种原因,我们从服务器端得到了一些错误的数据怎么办呢?如果订单既是正在加载又是已完成的呢?或者它已经完成但同时又包含错误?那么UI会是什么样子呢?CSS会使用其级联的特性来确定应用哪些样式,这可能会造成混乱。
因此,总结一下,当使用类来表示UI状态时,我们面临以下问题:
- 使用JavaScript手动将状态映射到类名。
- 检查元素上的类名是否存在以确定其状态。
- 当存在多个状态时,可能会出现样式冲突。
使用数据属性的更好方法
如果我告诉你有一种更好的方法?而且这种方法一直存在,已经有很多年了。我指的是数据属性。让我们看看如何使用它们来表示订单摘要的状态:
<div
id="order"
class="order-summary"
data-state="completed"
data-loading="false"
>
<!-- 订单摘要内容 -->
</div>
乍一看,我们只是将状态从JavaScript对象移动到DOM中。但这会有很大的不同。首先,我们不再需要将状态从JavaScript映射到DOM。我们只需在元素上设置数据属性即可:
// 假设我们想将订单的状态更改为加载中
const order = document.querySelector('#order');
order.dataset.state = 'loading';
order.dataset.loading = 'true';
我们还可以通过检查数据属性的值来检查订单的状态:
const order = document.querySelector('#order');
const isCompleted = order.dataset.state === 'completed';
const isLoading = order.dataset.loading === 'true';
const hasError = order.dataset.error === 'true';
JavaScript的值可以轻松从DOM中检索,没有隐藏的状态,并且很容易进行更改。但是CSS样式如何处理呢?好吧,我们只需要进行一些小的更改:
.order-summary[data-state="completed"] {
background-color: green;
}
.order-summary[data-state="loading"] {
background-color: yellow;
}
.order-summary[data-state="error"] {
background-color: red;
}
我们现在使用的是数据属性选择器,而不是类选择器。这使我们可以根据数据属性的值来定位元素。这比使用类更加灵活,因为我们现在可以在同一个元素上拥有多个状态,而不必担心冲突的样式。
但更有趣的是,我们无法遇到在同一个元素上有两个状态的问题。这是因为数据属性选择器需要完全匹配,否则它将不起作用。因此,如果我们有一个带有类似data-state="loading completed"
的元素,它将不匹配任何CSS选择器,也不会被样式化。从DOM中很容易发现它,并且可以确定出问题所在。
结论
正如你所看到的,使用HTML中的数据属性来表示状态比使用类更加灵活和可扩展。它强制我们更加明确和可调试。我认为这是使用类的一个很好的替代方案,希望你在下一个项目中考虑使用它。