Переключение класса в компоненте календаря по идентификатору элемента выделяет одну и ту же дату в каждом месяце - PullRequest
0 голосов
/ 24 мая 2019

Я написал простой календарь в Vue. Дни месяца отображаются с помощью v-for, который создает массив $ refs. Каждому элементу даты также присваивается уникальный идентификатор. Я хочу выделить день, нажав на него, и это работает. Тем не менее, тот же день в каждом месяце также выделяется. Например, если я нажму 25 мая, также будет выделено 25 числа каждого месяца, даже если я переключаю класс на основе идентификатора этого элемента.

Как выделить только выбранный день?

Вот код для метода выделения.

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

1 Ответ

1 голос
/ 25 мая 2019

Проблема, с которой вы сталкиваетесь, связана с использованием элементов DOM через $refs для хранения ваших выбранный день.

Я бы посоветовал вам отойти от логики такого типа (которую я называю логикой jQuery и, как правило, приводит к сложным манипуляциям с DOM, даже в простых случаях, например, у вас), на ту, которая специфична для SPA, где вы используете виртуальную модель. (обычно обозначаемый как 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 .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...