Vue für den kleinsten aka kleinen Blog auf allen Kanonen



Hallo allerseits! In diesem Artikel betrachten wir die Entwicklung der Vorderseite eines einfachen Vue-Blogs unter Verwendung aller Reize von Vue, einschließlich Vuex und Router. Lassen Sie uns auch über die Struktur der Anwendung sprechen und mit dem Container und dem Router arbeiten.

Zunächst definieren wir die Phasen der Erstellung der Front für die Anwendung (in diesem Fall das Blog):

  1. Planung
  2. Anwendungsskelett
  3. Modelle erstellen
  4. Implementierung der Geschäftslogik
  5. Seiten und Routen hinzufügen
  6. Komponenten hinzufügen
  7. Bearbeitungen

1. Planung


Zunächst werden wir aufschreiben, was unser SPA enthalten wird. Sie sollten direkt von den Seiten aus beginnen, da der Benutzer direkt damit interagiert (wenn es sehr grob ist, es ähnlich wie bei den TDD-Tests aufzurunden - wir beschreiben zuerst, was die Anwendung tun soll, wie der Benutzer damit interagiert, und dann sind wir bereits mit der Implementierung beschäftigt).

Also, welche Seiten werden sein:

  • Startseite - Hier finden Sie beliebte Kategorien, aktuelle Kommentare und Artikel
  • Kategorie durchsuchen - Eine Liste von Artikeln für eine bestimmte Kategorie.
  • Nachrichten anzeigen - direkt der Inhalt der Nachrichten und eine Liste von Kommentaren und anderen Artikeln aus der Kategorie

Wenn Sie Prototypen von Seiten einfügen, sieht es ungefähr so ​​aus:

Äußerste Schönheit


Nichts ist klar, aber das ist der Prototyp :-) Ich werde gleich erklären, warum es nicht mit Prototyping-Software gezeichnet wurde: weil es auf dem Papier viel schneller und einfacher ist und manchmal müssen Sie immer noch Ihre Hände bewegen, aber wenn es darum geht, wann Sie müssen irgendwo unterschreiben, wo es sehr traurig wird.

Basierend auf den Seiten, die wir erhalten, listen wir die Komponenten auf:

  • Liste der Artikel
  • Kategorieliste
  • Kommentarliste
  • Kommentarformular

Wir werden uns bereits bei der Implementierung der Komponenten selbst mit der Optimierung der Komponenten befassen, dies ist zum jetzigen Zeitpunkt nicht erforderlich.

Nachdem wir alle Benutzerinteraktionspunkte beschrieben haben, beschreiben wir schließlich das Wesentliche unserer Anwendung:

  • Artikel (Titel, Inhalt, Kommentarliste)
  • Kategorie (Überschrift, Nachrichtenliste)
  • Kommentar (Inhalt)

Es ist wichtig zu beachten, dass die Essenz der Geschäftslogik (BL) und nicht die Basistabelle beschrieben wird. Bei der Entwicklung und Planung der Vorderseite des Teils und des größten Teils der Rückseite (mit Ausnahme nur der Datenschicht) muss mit BL-Entitäten und nicht mit „Tabellen“ gearbeitet werden. Darüber hinaus sollten Entitäten nur das haben, was in der Anwendung selbst verwendet wird. Die Zukunft zu berühren ist gut, aber diese Zukunft kommt sehr selten, und wenn nur die verwendete Funktionalität festgelegt und die Anwendungsstruktur erweiterbar ist , gibt es keine Probleme mit dem Hinzufügen von Funktionalität in der Zukunft und es gibt zum gegenwärtigen Zeitpunkt nichts Überflüssiges.

2. Anwendungsskelett


Wir schaffen die Struktur. Wir führen die folgenden Befehle in der Konsole aus:

npm install -g @vue/cli vue create vue-blog-habr -n -d -m npm cd vue-blog-habr 

Diese Befehle erstellen das vue-blog-habr-Projekt im entsprechenden Verzeichnis. Weitere Informationen zu vue-cli und den verwendeten Parametern finden Sie hier .

Und am Ende erhalten wir die Standardprojektstruktur:



Installieren Sie sofort die Pakete, die wir benötigen:

 npm install vue-router vuex axios bootstrap-vue sass-loader npm install --save-dev --unsafe-perm node-sass 

Registrieren Sie die verwendeten Module:

src / main.js
 import App from './App.vue' import Vue from 'vue' import VueRouter from 'vue-router' import BootstrapVue from 'bootstrap-vue' import store from './store' import router from './router' Vue.config.productionTip = false Vue.use(VueRouter) Vue.use(BootstrapVue) new Vue({ store, router, render: h => h(App), }).$mount('#app') 


Wir korrigieren die Projektverzeichnisstruktur folgendermaßen:



Verzeichnisbeschreibung:

  • api - enthält Dateien, die für die "Kommunikation" mit dem Server verantwortlich sind
  • Vermögenswerte - verschiedene verwendete statische Ressourcen: Bilder, Symbole, ...
  • Komponenten - Anwendungskomponenten, ohne im Router verwendete "Seiten"
  • Modelle - Modelle der Geschäftslogik, sie können mit der Funktionalität der in der Front verwendeten Domäne gesättigt werden
  • pages - Seitenkomponenten, die im Router verwendet werden
  • Router - Routing-Dateien
  • services - Hilfsdienste, die nicht mit der Geschäftslogik zusammenhängen. Zum Beispiel der Anzeigedienst, der eine Methode zum Abrufen der Koordinaten eines Elements auf einer Seite enthält
  • store - Vuex-Speicherdateien
  • Stile - Stildateien

Führen Sie den Testserver aus:

 npm run serve 

Der letzte Befehl startet den Server, auf dem alle Projektbearbeitungen im Laufzeitmodus ausgeführt werden. Um auf den Browser zuzugreifen, gehen Sie zu: localhost : 8080

3. Modelle erstellen


In unserer Anwendung gibt es keine komplizierte Logik, aber Sie müssen trotzdem Modelle erstellen.
Dafür gibt es mehrere Gründe:

  • Objektspezifikation - Jedes beliebige Objekt kann beliebige Eigenschaften und Methoden enthalten. Wenn Klassen verwendet werden, wissen wir, welche Eigenschaften und Methoden ein bestimmtes Objekt hat
  • Eingabe von Komponentenparametern - folgt aus dem Vorherigen: Vue-Komponenten steuern die Art der Eingabeeigenschaften
  • Bequemlichkeit - in Bezug auf Klassen arbeiten wir mit Entitäten des Fachbereichs, wodurch der Code klarer wird. Klassen bieten auch zusätzliche Funktionen wie get / set / static

Alle Modelle werden in das entsprechende Verzeichnis gestellt. Die Klasse für den Artikel sieht folgendermaßen aus:

src / models / Article.js
 export default class Article { constructor(id, title, content) { this.id = id; this.title = title; this.content = content; this.comments = []; } addComment(item) { this.comments.push(item); } static createFrom(data) { const {id, title, content} = data; return new this(id, title, content); } } 


4. Implementierung der Geschäftslogik


Unerwartet, aber zu diesem Zeitpunkt ist die Implementierung der Geschäftslogik selbst NICHT erforderlich. Sie müssen ein Speicherobjekt erstellen und es sofort in Module aufteilen:

src / store / index.js
 import Vue from 'vue' import Vuex from 'vuex' import blog from './modules/blog' Vue.use(Vuex) export default new Vuex.Store({ modules: { blog, }, }) 


Und im Modul selbst werden wir alle verwendeten Mutationen / Getter / Aktionen weiter beschreiben. Das Repository sieht zunächst so aus:

src / store / modules / blog.js
 export default { state: {}, getters: {}, mutations: {}, actions: {}, } 


Zusätzlich starten wir ein Objekt für die Arbeit mit der API, durch das alle Anforderungen geleitet werden. Zum Zeitpunkt der Implementierung ist die Vorderseite des Teils, das Backend, absolut nicht erforderlich, sodass Sie statische Daten verwenden können:

src / api / index.js
 import Article from '@/models/Article'; import Comment from '@/models/Comment'; import Category from '@/models/Category'; export default { getArticles() { const comments = this.getComments(); const items = [ { id: 1, title: ' 1', content: '  1', }, { id: 2, title: ' 2', content: '  2', }, { id: 3, title: ' 3', content: '  3', }, { id: 4, title: ' 4', content: '  4', }, { id: 5, title: ' 5', content: '  5', }, { id: 6, title: ' 6', content: '  6', }, ]; return items.map((item) => { const article = Article.createFrom(item); article.comments = comments.filter((comment) => comment.article_id == article.id); return article; }); }, getComments() { const items = [ { id: 1, article_id: 1, content: '   1', }, ]; return items.map((item) => Comment.createFrom(item)) }, getCategories() { const items = [ { id: 1, title: '', articles: [1,3,5], }, { id: 2, title: '', articles: [2,3,4], }, { id: 3, title: '', articles: [], }, ]; return items.map((item) => Category.createFrom(item)) }, addComment(comment) { if (comment) { //     } }, }; 


Was gibt die Verwendung von Vuex:

  • Reinheit - Komponenten verwandeln sich nicht in Gottobjekte, die „zu viel wissen“
  • Konsistenz - Wenn Sie mehrere Komponenten haben, die dieselben Daten verwenden, werden diese (Daten) bei Verwendung des vuex-Containers beim Ändern von Daten in der gesamten Anwendung aktualisiert und nicht nur in der Komponente, die die Aktualisierung initiiert hat
  • Bequemlichkeit - Der Zugriff auf den Store ist viel einfacher und bequemer als die Beschreibung der Parametertypen und / oder API-Aufrufe in jeder Komponente
  • Tests - obwohl wer es tut?

5. Seiten und Routen hinzufügen


Basierend auf der zuvor geplanten Struktur müssen 4 Seiten erstellt werden: Index, Kategorie, Artikel sowie 404 Seiten. Fügt im Verzeichnis src / pages die entsprechenden Dateien hinzu:

  • Article.vue
  • Category.vue
  • Index.vue
  • 404.vue

Wenn 404 Seiten eine persönliche Seite mit einem individuellen Design haben sollen, kann der Einstiegspunkt folgendermaßen geändert werden:

src / app.vue
 <template> <div id="app"> <template v-if="is404"> <router-view></router-view> </template> <template v-else> <Header></Header> <main> <b-container> <router-view></router-view> </b-container> </main> </template> </div> </template> <script> import '@/styles/index.scss'; import Header from '@/components/Header.vue'; export default { name: 'App', components: { Header, }, computed: { is404() { return this.$route.name === '404'; }, }, } </script> 


Die Hauptseitendatei sieht folgendermaßen aus:

src / pages / Index.vue
 <template> <b-row> <b-col md="8" lg="9"> <ListItems :items="lastArticles"> <template v-slot:default="props"> <ArticleItem :item="props.item"></ArticleItem> </template> <template v-slot:empty>    :) </template> </ListItems> </b-col> <b-col md="4" lg="3"> <ListItems :items="popularCategories" v-slot="props"> <router-link :to="getCategoryRoute(props.item)"> {{ props.item.title }} </router-link> </ListItems> <CommentItem v-for="(item, index) in lastComments" :key="index" :item="item"></CommentItem> </b-col> </b-row> </template> <script> import ListItems from '@/components/ListItems.vue' import ArticleItem from '@/components/ArticleItem.vue' import CommentItem from '@/components/CommentItem.vue' import { mapGetters, } from 'vuex' export default { name: 'Index', components: { ListItems, ArticleItem, CommentItem, }, data() { return {}; }, methods: { getCategoryRoute(item) { return { name: 'Category', params: { category_id: item.id, }, }; }, }, computed: { ...mapGetters([ 'lastArticles', 'lastComments', 'popularCategories', ]), }, created() { /** *     (  ) */ this.$store.dispatch('loadArticles'); this.$store.dispatch('loadComments'); this.$store.dispatch('loadCategories'); }, } </script> 


Nach der Implementierung der Seiten fügen wir sofort alle verwendeten Getter und Aktionen zum vuex-Repository hinzu (ohne Implementierung):

src / store / modules / blog.js
 export default { state: { articles: [], comments: [], categories: [], // activeArticle: null, activeCategory: null, }, getters: { lastArticles(state) { return []; }, lastComments(state) { return []; }, popularCategories(state) { return []; }, activeCategoryArticles(state) { return []; }, }, mutations: {}, actions: { async loadArticles({ commit, state }) {}, async loadComments({ commit, state }) {}, async loadCategories({ commit, state }) {}, async loadActiveCategory(context, id) {}, async loadActiveArticle(context, id) {}, async addComment({ commit }, payload) {}, }, } 


Es gibt mehrere Punkte zu beachten:

  • Wenn Sie Daten abrufen möchten, müssen Sie sich an state wenden. Wenn Sie nach dem Empfang der Daten eine Manipulation der Daten vornehmen müssen, ist es besser, Getter dafür zu erstellen.
  • Wenn Sie etwas mit Daten tun müssen, müssen Sie sich auf Aktionen beziehen, nicht auf Mutationen. Eine Aktion kann mehrere Mutationen umfassen und andere Datenmanipulationen sowie das Schreiben in den Status ausführen und unterliegt keinen asynchronen Einschränkungen
  • Es müssen keine direkten Anfragen an die API / Rest gestellt werden. Wenn Sie alle Daten über Vuex anfordern, wird der konsistente Zustand der gesamten Anwendung garantiert (wenn die Speicherung selbst korrekt durchgeführt wird).
  • In allen Links und der Programmnavigation müssen Sie sich auf benannte Routen beziehen. Auf diese Weise können Sie die Routen selbst problemlos ändern, ohne die Links und die Programmnavigation zu bearbeiten. Hierbei handelt es sich natürlich um Links innerhalb des SPA, Adressen, die nicht vom Router verarbeitet werden, müssen wie gewohnt angegeben werden

Nachdem Sie die Seiten selbst erstellt und gefüllt haben, müssen Sie dem Router die entsprechenden Regeln hinzufügen:

src / router / index.js
 import VueRouter from 'vue-router' import blog from './blog' export default new VueRouter({ mode: 'history', routes: [ { path: '/', name: 'Index', component: () => import('@/pages/Index.vue'), }, /** *   ,       *     *          */ ...blog, { path: '*', name: '404', component: () => import('@/pages/404.vue'), }, ] }) 


Alle Router-Parameter finden Sie in der Dokumentation: router.vuejs.org/ru/api/#constructor options-router

6. Komponenten hinzufügen


Nach der Implementierung aller Seiten erhalten wir die folgende Liste von Komponenten, die wichtigsten:

  • CategoryItem
  • ArticleItem
  • CommentItem
  • CommentForm

Und Hilfs:

  • ListItems
  • Header

Da wir bei der Implementierung von Komponenten Modelle verwenden, können wir diese zur Typisierung von Parametern verwenden:

src / components / ArticleItem.vue
 <template> <b-card :title="item.title" class="article-item-card"> <router-link :to="getArticleRoute" class="card-link">  </router-link> </b-card> </template> <script> import Article from '@/models/Article'; export default { name: 'ArticleItem', props: { item: Article, }, computed: { getArticleRoute() { return { name: 'Article', params: { post_id: this.item.id, }, }; }, }, } </script> <style> .article-item-card { margin-bottom: 1rem; } </style> 


Ein paar Worte über die Implementierung von Komponenten auf der Haupt:

src / pages / Index.vue
 <template> <b-row> <b-col md="8" lg="9"> <ListItems :items="lastArticles"> <template v-slot:default="props"> <ArticleItem :item="props.item"></ArticleItem> </template> <template v-slot:empty>    :) </template> </ListItems> </b-col> <b-col md="4" lg="3"> <ListItems :items="popularCategories" v-slot="props"> <router-link :to="getCategoryRoute(props.item)"> {{ props.item.title }} </router-link> </ListItems> <CommentItem v-for="(item, index) in lastComments" :key="index" :item="item"></CommentItem> </b-col> </b-row> </template> <script> import ListItems from '@/components/ListItems.vue' import ArticleItem from '@/components/ArticleItem.vue' import CommentItem from '@/components/CommentItem.vue' import { mapGetters, } from 'vuex' export default { name: 'Index', components: { ListItems, ArticleItem, CommentItem, }, data() { return {}; }, methods: { getCategoryRoute(item) { return { name: 'Category', params: { category_id: item.id, }, }; }, }, computed: { ...mapGetters([ 'lastArticles', 'lastComments', 'popularCategories', ]), }, created() { /** *     (  ) */ this.$store.dispatch('loadArticles'); this.$store.dispatch('loadComments'); this.$store.dispatch('loadCategories'); }, } </script> 


Diese Seite verwendet die Wrapper-Komponente von ListItems. Auf den ersten Blick mag es redundant erscheinen, da Sie mit dem v-for-Konstrukt auskommen können, wenn Kommentare gemacht werden, aber die Verwendung von Slots reduziert den verwendeten Code erheblich und ermöglicht es Ihnen, dasselbe Element an mehreren Stellen wiederzuverwenden.

Wenn Sie sich jedoch die Artikelliste ansehen, wird sie auf zwei Seiten (Index und Kategorie) mit genau demselben Aufruf verwendet. In dieser Situation ist es die richtige Entscheidung, die ArticleItems-Komponente zu erstellen und von ListItems zu erben:

src / components / ArticleItems.vue
 <template> <ListItems :items="items"> <template v-slot:default="props"> <ArticleItem :item="props.item"></ArticleItem> </template> <template v-slot:empty>    :) </template> </ListItems> </template> <script> import ListItems from '@/components/ListItems.vue' import ArticleItem from '@/components/ArticleItem.vue' export default { name: 'ArticleItems', components: { ArticleItem, ListItems, }, extends: ListItems, } </script> 


In diesem Fall erlaubt die Vererbung, die Beschreibung der Parameter (Eigenschaft props) nicht zu duplizieren, sondern wird von der übergeordneten Komponente übernommen. Weitere Informationen zu Vererbung und Verunreinigungen: ru.vuejs.org/v2/api/#extends , ru.vuejs.org/v2/guide/mixins.html

Nach dem Erstellen einer neuen Komponente müssen Sie auch die Auslagerungsdateien korrigieren:

src / pages / Category.vue (was)
 <template> <div> <div v-if="category"> <h1> {{ category.title }} </h1> <ListItems :items="articles"> <template v-slot:default="props"> <ArticleItem :item="props.item"></ArticleItem> </template> <template v-slot:empty>    :) </template> </ListItems> </div> <div v-else>    </div> </div> </template> <script> import ListItems from '@/components/ListItems.vue' import ArticleItem from '@/components/ArticleItem.vue' import { mapActions, } from 'vuex' export default { name: 'Category', components: { ListItems, ArticleItem, }, computed: { categoryId() { return this.$route.params['category_id'] || null; }, category() { return this.$store.state.blog.activeCategory; }, articles() { return this.$store.getters.activeCategoryArticles; }, }, methods: { ...mapActions([ 'loadActiveCategory', ]), }, mounted() { this.loadActiveCategory(this.categoryId); }, } </script> 


src / pages / Category.vue (wurde)
 <template> <div> <div v-if="category"> <h1> {{ category.title }} </h1> <ArticleItems :items="articles"></ArticleItems> </div> <div v-else>    </div> </div> </template> <script> import ArticleItems from '@/components/ArticleItems.vue' import { mapActions, } from 'vuex' export default { name: 'Category', components: { ArticleItems, }, computed: { categoryId() { return this.$route.params['category_id'] || null; }, category() { return this.$store.state.blog.activeCategory; }, articles() { return this.$store.getters.activeCategoryArticles; }, }, methods: { ...mapActions([ 'loadActiveCategory', ]), }, mounted() { this.loadActiveCategory(this.categoryId); }, } </script> 


Beachten Sie auch das Formular zum Hinzufügen von Kommentaren. Anfragen werden nicht direkt an die API gerichtet, sondern die Vuex-Aktion wird ausgeführt und die Anfrage an die API befindet sich bereits „im Inneren“, das erforderliche Artikelmodell wird aktualisiert und die Liste der Kommentare wird aktualisiert. Der Code der Komponente selbst sieht folgendermaßen aus:

src / components / CommentForm.vue
 <template> <form @submit.prevent="onSubmit"> <textarea class='form-control' v-model="content"></textarea> <br> <button type="submit" class="btn btn-primary"></button> </form> </template> <script> export default { name: 'CommentForm', props: { articleId: Number, }, data() { return { content: '', }; }, methods: { onSubmit() { if (this.content) { this.$store.dispatch('addComment', { content: this.content, article_id: this.articleId, }); this.content = ''; } }, }, } </script> 


In diesem speziellen Fall ist der vordere Teil des Blogs fertig, nachdem alle Komponenten und Seiten implementiert, Stubs implementiert und Testdaten hinzugefügt wurden. Aber wie es in der Praxis üblich ist, ist dies noch lange nicht das Ende des Projekts, denn nach Abschluss der Arbeiten beginnen die Änderungen :-)

7. Bearbeitungen


Angenommen, wir müssen die Anzeige von Artikeln auf der Kategorieseite ändern: Sie sollten in zwei Spalten angezeigt werden. Und auf der Hauptseite soll alles so bleiben, wie es ist.

Wir fügen der Anzahl der Spalten in der ArticleItems-Komponente eine zusätzliche cols-Eigenschaft hinzu.

src / components / ArticleItems.vue (wurde)
 <template> <ListItems :items="items" class="row"> <template v-slot:default="props"> <b-col :cols="itemCols"> <ArticleItem :item="props.item"></ArticleItem> </b-col> </template> <template v-slot:empty> <b-col>    :) </b-col> </template> </ListItems> </template> <script> import ListItems from '@/components/ListItems.vue' import ArticleItem from '@/components/ArticleItem.vue' export default { name: 'ArticleItems', components: { ArticleItem, ListItems, }, extends: ListItems, props: { cols: { type: Number, default: 1, }, }, computed: { itemCols() { return 12 / this.cols; }, }, } </script> 


Fügen Sie im Komponentenaufruf auf der Kategorieseite die gewünschte Eigenschaft hinzu:

src / pages / Category.vue
 <ArticleItems :items="articles" :cols="2"></ArticleItems> 


Dann wollten wir zur Artikelansichtsseite gehen und Links zu benachbarten Artikeln hinzufügen (vorwärts / rückwärts). Dazu müssen Sie der Seite 2 Getter und Links hinzufügen:

src / pages / Article.vue
 <template> <b-row v-if="article"> <b-col md="8" lg="9"> <h1> {{ article.title }} </h1> <p class="mb-4"> {{ article.content }} </p> <table class="table table-bordered"> <tbody> <tr> <td class="w-50"> <router-link v-if="prevArticle" :to="getArticleRoute(prevArticle)"> {{ prevArticle.title }} </router-link> </td> <td class="text-right"> <router-link v-if="nextArticle" :to="getArticleRoute(nextArticle)"> {{ nextArticle.title }} </router-link> </td> </tr> </tbody> </table> <CommentForm :articleId="article.id"></CommentForm> <CommentItem v-for="(item, index) in article.comments" :key="index" :item="item"></CommentItem> </b-col> <b-col md="4" lg="3"> <CommentItem v-for="(item, index) in lastComments" :key="index" :item="item"></CommentItem> </b-col> </b-row> </template> <script> import CommentForm from '@/components/CommentForm.vue'; import CommentItem from '@/components/CommentItem.vue'; import { mapActions, mapGetters, } from 'vuex' export default { name: 'Article', components: { CommentForm, CommentItem, }, computed: { ...mapGetters([ 'lastComments', 'nextArticle', 'prevArticle', ]), articleId() { return this.$route.params['post_id'] || null; }, article() { return this.$store.state.blog.activeArticle; }, }, methods: { ...mapActions([ 'loadComments', 'loadActiveArticle', ]), getArticleRoute(item) { return { name: 'Article', params: { post_id: item.id, }, }; }, }, mounted() { this.loadComments(); this.loadActiveArticle(this.articleId); }, watch: { articleId(value) { this.loadActiveArticle(value); }, }, } </script> 


Und die Umsetzung der Getter selbst:

src / store / modules / blog.js
 ... prevArticle(state) { let prevItem = null; if (state.activeArticle) { state.articles.forEach((item, index) => { if (item.id == state.activeArticle.id) { prevItem = state.articles[index-1] || null; } }); } return prevItem; }, nextArticle(state) { let nextItem = null; if (state.activeArticle) { state.articles.forEach((item, index) => { if (item.id == state.activeArticle.id) { nextItem = state.articles[index+1] || null; } }); } return nextItem; }, ... 


Und schließlich müssen wir die URL für die Artikelseite von "Artikel-123" in "Post-123" ändern. Da in der gesamten Anwendung benannte Routen verwendet werden, reicht es aus, nur das Routenmuster zu ändern:

src / router / blog / index.js
 export default [ { path: '/cat-:category_id', name: 'Category', component: () => import('@/pages/Category.vue'), }, { path: '/post-:post_id', name: 'Article', component: () => import('@/pages/Article.vue'), }, ]; 



Nützliche Literatur


  1. vuex.vuejs.org/en/guide
  2. cli.vuejs.org/en/guide
  3. router.vuejs.org/ru


PS


Obwohl dies eine sehr einfache Anwendung war, ist die Struktur so aufgebaut, dass Sie leicht etwas ändern und / oder hinzufügen können:

  • Die Komponenten beschäftigen sich ausschließlich mit der Visualisierung, die Daten werden in Form von Modellen aus dem Repository entnommen und es werden keine direkten API-Anfragen gestellt.
  • Modelle enthalten die erforderliche Geschäftslogik und alle Beziehungen zwischen Entitäten. Greifen Sie auch NICHT auf die API zu.
  • Speicher (vuex) ist das Verbindungsglied aller Komponenten: Daten werden von der API angefordert und in Modelle konvertiert, auf die die Komponenten dann zugreifen.

Optisch kann dies folgendermaßen dargestellt werden:


Mit diesem Schema kann die Arbeit am Projekt sicher auf drei Einheiten aufgeteilt werden:

  • Mr. Layout - befasst sich mit der Implementierung von Seiten und Komponenten und beschreibt auch, welche Felder Modelle enthalten sollen und welche Getter und Aktionen sich im Repository befinden sollen.
  • Mr. Front - beschäftigt sich mit der Implementierung von Geschäftslogik- und Vuex-Speichermodellen sowie dem Routing und allem anderen, was Mr. Layout nicht betrifft.
  • Herr Back - ist mit der Implementierung von API-Diensten auf der Back-End-Seite beschäftigt.

Alle Einheiten können unabhängig voneinander arbeiten, wenn zuvor alle Gemeinsamkeiten besprochen wurden (im Allgemeinen, wenn vor der Arbeit an dem Projekt eine Planung vorhanden war).

Oder wenn es kein Team als solches gibt, ist es logisch, von oben nach unten zu gehen, damit es so schnell wie möglich etwas zu sehen gibt (MVP ausrollen).

Repository mit allen Quellen: github.com/irpsv/vue-blog-habr

Source: https://habr.com/ru/post/de483064/


All Articles