add template component

This commit is contained in:
Владимир Фёдоров 2026-03-18 00:47:08 +07:00
parent 200704bf92
commit 365a231ed5

View File

@ -0,0 +1,90 @@
<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>