Прогресс
Трекер должен показывать с первого взгляда, как идёт ваш день: Сегодня выполнено: 2 / 5, полосу, которая заполняется по мере того, как вы отмечаете привычки, и похвалу, когда сделано всё.
Всё это считается из habits, поэтому здесь нужны вычисляемые значения, как в уроке «Вычисляемые значения и наблюдатели». Vue пересчитывает их при каждом изменении привычки, и страница меняется вместе с ними:
const doneCount = computed(() => {
return habits.value.filter((habit) => habit.done).length;
});
const percent = computed(() => {
if (habits.value.length === 0) {
return 0;
}
return Math.round((doneCount.value / habits.value.length) * 100);
});
const allDone = computed(() => {
return habits.value.length > 0 && doneCount.value === habits.value.length;
});
doneCount — сколько привычек выполнено, а percent — какую долю от всех они составляют, в процентах: 2 из 5 — это 40. Math.round() округляет до целого числа (1 из 3 было бы 33,333…). Без if в списке без привычек произошло бы деление на ноль, а в JavaScript 0 / 0 — это NaN, «не число». allDone равно true, когда выполнена каждая привычка, но не когда привычек нет вовсе.
Полоса состоит из двух элементов: серой ленты с классом bar и зелёной внутри неё с классом fill; оба оформлены в style.css. Ширина зелёной равна проценту. Ширина меняется, поэтому она идёт в :style, как в уроке «Синтаксис шаблонов», а раз CSS нужна единица измерения, к числу добавляется '%':
<div class="progress">
<p>Сегодня выполнено: {{ doneCount }} / {{ habits.length }}</p>
<div class="bar">
<div class="fill" :style="{ width: percent + '%' }"></div>
</div>
<p v-if="allDone">Всё сделано на сегодня! 🎉</p>
</div>
Прогресс относится к загруженной странице, поэтому показывать его нужно только вместе со списком, под v-else. Но v-else может быть только у одного элемента, поэтому оберните оба в <template v-else>, как в уроке «Условия и списки»: он группирует их, не добавляя на страницу лишнего элемента.
Типичные ошибки:
doneCount / habits.value.lengthбез.valueуdoneCount. В скрипте вычисляемое значение — тоже реф, и деление самого рефа даётNaN, поэтому полоса остаётся пустой.width: percentбез'%'. Браузер игнорирует ширину без единицы измерения, и полоса не растёт.
Задание
- 1
Добавьте
computedв импорт из"vue"и напишите три вычисляемых значения из примера под рефами. В шаблоне оберните список в<template v-else>(уulv-elseбольше не нужен) и в начало<template v-else>поставьтеdivс классомprogressиз примера, пока только с первым абзацем. Отметьте привычку:Сегодня выполнено: 1 / 5. - 2
Добавьте в
divполосу и похвалу, как в примере выше. Отметьте две привычки — полоса заполнится на 40%. Отметьте все, и страница вас похвалит.