首页 > 解决方案 > 按元素 ID 切换日历组件中的类突出显示每个月的相同日期

问题描述

我在 Vue 中编写了一个简单的日历。通过使用 v-for 创建一个 $refs 数组来显示月份中的日期。每个日期元素也被赋予一个唯一的 ID。我想通过单击它来突出显示一天,这很有效。但是,每个月的同一天也会突出显示。例如,如果我单击 5 月 25 日,则每隔一个月的 25 日也会突出显示,即使我是基于该元素的 id 切换类。

如何仅突出显示选定的日期?

这是 highlight 方法的代码。

highlightDay(index) {
                let selected = this.$refs.day[index].id;
                if (!this.$refs.day[index].classList.contains("today")) {
                    this.$refs.day.forEach(el => {
                        if (el.classList.contains("selected-day")) {
                            el.classList.toggle("selected-day");
                        }
                    });
                    document
                        .getElementById(selected)
                        .classList.toggle("selected-day");
                }
            }

这是该项目的链接。 https://codepen.io/reticent67/pen/EzWomG

标签: javascriptvue.jsvuejs2

解决方案


您面临的问题来自使用 DOM 元素,通过$refs,来存储您选择的日期。

我会鼓励你从那种类型的逻辑(我称之为 jQuery 逻辑,通常会导致复杂的 DOM 操作,即使在像你这样的简单情况下)转移到特定于 SPA 的逻辑中,在那里你使用虚拟模型(通常指to as vm) 作为事实的来源1

回到您的组件,而不是将您选择的日期存储为id当前渲染的日期,我将其存储为一个数组,具有 3 个元素:[day, month, year] 2

要将其传递给渲染层,您应该使用以下方法:

isSelected(index) {
  return this.selectedDay === [index, this.month, this.year];
}

日期标记包含以下内容:

<div 
  v-for="(date, date_index) in months[month].days" 
  :key="date_index" 
  :class="[{ 'selected-day': isSelected(date_index) }]">{{ date }}
</div>

我已在您的示例中实现了这一点
注意我还简化了highlightDay()方法。selectedDay如果它们相等,我只需将其设置为上述数组或取消设置(通过单击选定的一个来启用取消选择)。


[1] - 请注意,在更复杂的情况下,需要在应用程序组件之间共享事实来源,Vue 提供了一个专门的模块来管理数据,称为 Vuex(但我们在这里不使用它)。

[2] - 为了清理观察者的数据(Vue 用来监听突变),我将数组存储selectedDay为 JSON 字符串。


推荐阅读