8.1 KiB
8.1 KiB
Posts Form Components Guide
Структура компонентов
Posts/Form.vue (1284 строки) разбит на переиспользуемые подкомпоненты:
Posts/Components/
├── PostMainInfo.vue # Заголовок, slug, статус, категория
├── PostTagsAuthors.vue # Теги и авторы
└── PostPublishSettings.vue # Настройки публикации и соцсети
Как использовать
1. PostMainInfo.vue
Основная информация о посте.
<PostMainInfo
v-model:title="form.title"
v-model:slug="form.slug"
v-model:status="form.status"
v-model:category-id="form.category_id"
:categories="categories"
:status-options="[PostStatus.DRAFT, PostStatus.PUBLISHED, PostStatus.VERIFICATION, PostStatus.REJECTED]"
:errors="form.errors"
@generate-slug="generateSlug"
/>
Props:
title- заголовок новостиslug- URL-адресstatus- статус публикацииcategoryId- ID категорииcategories- массив категорийstatusOptions- массив опций статусаerrors- объект ошибок валидацииinputClass- CSS классы для инпутов
Events:
update:title- обновление заголовкаupdate:slug- обновление slugupdate:status- обновление статусаupdate:categoryId- обновление категорииgenerate-slug- генерация slug из заголовка
2. PostTagsAuthors.vue
Управление тегами и авторами.
<PostTagsAuthors
:tags="form.tags"
:authors="form.authors"
@add-tag="addTag"
@remove-tag="removeTag"
@add-author="addAuthor"
@remove-author="removeAuthor"
/>
Props:
tags- массив теговauthors- массив авторов
Events:
add-tag- добавить тегremove-tag- удалить тег по индексуadd-author- добавить автораremove-author- удалить автора по индексу
3. PostPublishSettings.vue
Настройки публикации и социальных сетей.
<PostPublishSettings
v-model:publish-after="form.publish_setting.publish_after"
v-model:publish-at="form.publish_setting.publish_at"
v-model:publish-vk="form.publication.vk"
:errors="form.errors"
/>
Props:
publishAfter- флаг отложенной публикацииpublishAt- дата/время публикацииpublishVk- публикация ВКонтактеerrors- объект ошибок валидацииinputClass- CSS классы для инпутов
Events:
update:publishAfter- обновление флага отложенной публикацииupdate:publishAt- обновление даты/времениupdate:publishVk- обновление флага VK
Пример интеграции в Form.vue
BEFORE (монолитный подход):
<!-- Внутри Form.vue - 1284 строки -->
<div class="space-y-6">
<!-- Title & Slug -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-5">
<!-- 50+ строк markup -->
</div>
<!-- Status & Category -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-5">
<!-- 40+ строк markup -->
</div>
<!-- Tags -->
<div>
<!-- 60+ строк markup -->
</div>
<!-- Authors -->
<div>
<!-- 60+ строк markup -->
</div>
<!-- Publishing Settings -->
<div class="border border-layer-line rounded-lg overflow-hidden">
<!-- 80+ строк markup -->
</div>
<!-- Social Media -->
<div class="border border-layer-line rounded-lg overflow-hidden">
<!-- 50+ строк markup -->
</div>
</div>
AFTER (компонентный подход):
<template>
<div class="min-h-screen bg-background-2">
<!-- Sticky Header -->
<div class="border-b border-line-2 bg-layer/50 backdrop-blur-sm sticky top-0 z-20">
<!-- Header content -->
</div>
<!-- Main Content -->
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
<FlashMessages />
<form @submit.prevent="submitForm" class="space-y-6">
<!-- Tabs Navigation -->
<div class="bg-layer border border-layer-line rounded-lg shadow-xs overflow-hidden">
<div class="border-b border-line-2">
<!-- Tab buttons -->
</div>
<!-- Tab Content -->
<div class="p-6">
<!-- Tab: Main Info -->
<div v-show="activeTab === 'main'" class="space-y-6">
<PostMainInfo
v-model:title="form.title"
v-model:slug="form.slug"
v-model:status="form.status"
v-model:category-id="form.category_id"
:categories="categories"
:status-options="statusOptions"
:errors="form.errors"
@generate-slug="generateSlug"
/>
<PostTagsAuthors
:tags="form.tags"
:authors="form.authors"
@add-tag="addTag"
@remove-tag="removeTag"
@add-author="addAuthor"
@remove-author="removeAuthor"
/>
<PostPublishSettings
v-model:publish-after="form.publish_setting.publish_after"
v-model:publish-at="form.publish_setting.publish_at"
v-model:publish-vk="form.publication.vk"
:errors="form.errors"
/>
</div>
<!-- Tab: Content -->
<div v-show="activeTab === 'content'">
<!-- Content builder stays as is -->
</div>
<!-- Tab: Media -->
<div v-show="activeTab === 'media'">
<!-- Media management -->
</div>
<!-- Tab: Slider -->
<div v-show="activeTab === 'slider'">
<!-- Slider settings -->
</div>
</div>
</div>
</form>
</div>
</div>
</template>
<script>
import PostMainInfo from './Components/PostMainInfo.vue';
import PostTagsAuthors from './Components/PostTagsAuthors.vue';
import PostPublishSettings from './Components/PostPublishSettings.vue';
export default {
components: {
PostMainInfo,
PostTagsAuthors,
PostPublishSettings
},
methods: {
addTag(tag) {
this.form.tags.push(tag);
},
removeTag(index) {
this.form.tags.splice(index, 1);
},
addAuthor(author) {
this.form.authors.push(author);
},
removeAuthor(index) {
this.form.authors.splice(index, 1);
},
generateSlug() {
if (!this.form.slug && this.form.title) {
this.form.slug = this.slugify(this.form.title);
}
}
}
}
</script>
Преимущества рефакторинга
До:
- 1284 строки в одном файле
- Сложно искать и отлаживать
- Невозможно переиспользовать
- Долгая загрузка
После:
- ~300-400 строк в Form.vue (только логика)
- 3 переиспользуемых компонента (~150 строк каждый)
- Легко тестировать изолированно
- Можно использовать в других формах (например, редактирование новостей)
- Улучшенная читаемость
Следующие шаги
- Заменить в Form.vue использование этих компонентов
- Создать дополнительные компоненты:
PostContentBuilder.vue- конструктор контентаPostMediaUploader.vue- загрузка медиаPostSliderConfig.vue- настройка слайдера
- Протестировать все сценарии создания/редактирования