91 lines
2.2 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script setup lang="ts">
import { computed, ref, watch } from 'vue'
// Интерфейсы и типы
export interface Todo {
id: number
title: string
completed: boolean
priority: 'low' | 'medium' | 'high'
createdAt: Date
tags?: string[]
}
// Тип для пропсов
interface Props {
todo: Todo
showPriority?: boolean
index?: number
}
// Тип для событий
interface Emits {
(e: 'update', todo: Todo): void
(e: 'delete', id: number): void
(e: 'click', index: number): void
}
// Определение пропсов с типами
const props = withDefaults(defineProps<Props>(), {
showPriority: true,
index: 0
})
// Определение событий с типами
const emit = defineEmits<Emits>()
// Реактивные данные с типами
// const isHovered = ref<boolean>(false)
const clickCount = ref<number>(0)
// Вычисляемые свойства с типами
const priorityClass = computed((): string => {
const priorityMap = {
low: 'priority-low',
medium: 'priority-medium',
high: 'priority-high'
}
return priorityMap[props.todo.priority]
})
// Методы с типами
const handleClick = (event: MouseEvent): void => {
clickCount.value++
emit('click', props.index)
console.log(`Клик #${clickCount.value}`, event)
}
const toggleComplete = (event: Event): void => {
const input = event.target as HTMLInputElement
const updatedTodo: Todo = {
...props.todo,
completed: input.checked
}
emit('update', updatedTodo)
}
const deleteTodo = (): void => {
emit('delete', props.todo.id)
}
// Типизированные watchers
watch(() => props.todo.completed, (newValue: boolean, oldValue: boolean) => {
console.log(`Статус изменен: ${oldValue} -> ${newValue}`)
})
</script>
<template>
<div class="todo-item" :class="{ completed: todo.completed }" @click="handleClick">
<input type="checkbox" :checked="todo.completed" @change="toggleComplete" />
<span>{{ todo.title }}</span>
<span class="priority" :class="priorityClass">
{{ todo.priority }}
</span>
<button @click.stop="deleteTodo">Удалить</button>
</div>
</template>
<style scoped>
/* стили компонента */
</style>