Vue untuk blog kecil alias terkecil di semua kanon



Halo semuanya! Pada artikel ini, kami akan mempertimbangkan pengembangan bagian depan blog Vue sederhana menggunakan semua pesona Vue termasuk Vuex dan Router. Dan juga mari kita bicara tentang struktur aplikasi dan bekerja dengan wadah dan router.

Pertama, kita akan menentukan tahapan membuat bagian depan untuk aplikasi (dalam hal ini, blog):

  1. perencanaan
  2. kerangka aplikasi
  3. membuat model
  4. implementasi logika bisnis
  5. menambahkan halaman dan rute
  6. menambahkan komponen
  7. suntingan

1. Perencanaan


Untuk mulai dengan, kami akan menuliskan apa yang akan mengandung SPA kami. Anda harus mulai langsung dari halaman, karena ini adalah apa yang berinteraksi langsung dengan pengguna (jika sangat sulit untuk mengumpulkannya mirip dengan tes TDD - kami pertama-tama menggambarkan apa yang harus dilakukan aplikasi, bagaimana pengguna akan berinteraksi dengannya, dan kemudian kami sudah terlibat dalam implementasi).

Jadi halaman apa yang akan:

  • Rumah - ini akan menampilkan kategori populer, komentar terbaru dan artikel
  • Browse Category - Daftar artikel untuk kategori tertentu.
  • Lihat berita - langsung isi berita dan daftar komentar, dan artikel lain dari kategori

Jika Anda meletakkan prototipe halaman, maka tampilannya seperti ini:

Keindahan total


Tidak ada yang jelas, tapi itu prototipe :-) Saya akan segera menjelaskan mengapa itu tidak ditarik menggunakan perangkat lunak prototyping: karena jauh lebih cepat dan lebih mudah di atas kertas, dan kadang-kadang Anda masih perlu menggerakkan tangan Anda, tetapi ketika tiba saatnya ketika Anda harus masuk ke suatu tempat yang sangat menyedihkan.

Berdasarkan halaman yang kami dapatkan, kami membuat daftar komponen:

  • Daftar Artikel
  • Daftar Kategori
  • Daftar komentar
  • Formulir komentar

Kami akan berurusan dengan optimalisasi komponen sudah selama implementasi komponen itu sendiri, pada tahap ini ini tidak perlu.

Akhirnya, setelah menjelaskan semua poin interaksi pengguna, kami menjelaskan esensi dari aplikasi kami:

  • Artikel (judul, konten, daftar komentar)
  • Kategori (berita utama, daftar berita)
  • Komentar (konten)

Penting untuk dicatat bahwa esensi logika bisnis (BL) dijelaskan, dan bukan tabel dasar. Ketika mengembangkan dan merencanakan bagian depan, dan sebagian besar bagian belakang (tidak termasuk hanya lapisan data), perlu untuk beroperasi dengan entitas BL, dan tidak dengan "tabel". Selain itu, entitas seharusnya hanya memiliki apa yang digunakan dalam aplikasi itu sendiri. Menyentuh masa depan itu baik, tetapi sangat jarang masa depan ini datang, dan dalam hal ketika hanya fungsionalitas yang digunakan diletakkan dan struktur aplikasi diperluas , tidak ada masalah dengan menambahkan fungsionalitas di masa depan dan tidak ada yang berlebihan pada saat ini.

2. Kerangka Aplikasi


Kami beralih ke menciptakan struktur. Kami menjalankan perintah berikut di konsol:

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

Perintah-perintah ini membuat proyek vue-blog-habr di direktori yang sesuai. Informasi lebih lanjut tentang vue-cli dan parameter yang digunakan dapat ditemukan di sini .

Dan pada akhirnya kami mendapatkan struktur proyek standar:



Segera instal paket yang kami butuhkan:

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

Daftarkan modul yang digunakan:

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') 


Kami memperbaiki struktur direktori proyek dengan cara ini:



Deskripsi Direktori:

  • api - berisi file yang bertanggung jawab untuk "komunikasi" dengan server
  • aset - berbagai sumber daya statis yang digunakan: gambar, ikon, ...
  • komponen - komponen aplikasi, tanpa "halaman" yang digunakan di router
  • model - model logika bisnis, mereka dapat jenuh dengan fungsionalitas dari domain yang digunakan di depan
  • halaman - komponen halaman yang digunakan dalam router
  • router - merutekan file
  • layanan - layanan tambahan yang tidak terkait dengan logika bisnis. Misalnya, layanan Tampilan, yang berisi metode untuk mendapatkan koordinat elemen pada halaman
  • store - file penyimpanan Vuex
  • gaya - gaya file

Dan jalankan server uji:

 npm run serve 

Perintah terakhir memulai server di mana semua pengeditan proyek diterapkan dalam mode runtime. Untuk mengakses browser, buka: localhost : 8080

3. Membuat model


Tidak ada logika yang rumit dalam aplikasi kami, namun demikian, Anda perlu membuat model dalam hal apa pun.
Ada beberapa alasan untuk ini:

  • spesifikasi objek - objek sembarang, dapat berisi properti dan metode apa pun. Ketika kelas digunakan, kita tahu properti dan metode apa yang dimiliki objek tertentu
  • pengetikan parameter komponen - mengikuti dari yang sebelumnya: Komponen Vue mengontrol tipe properti input
  • kenyamanan - dalam hal kelas, kami beroperasi dengan entitas dari area subjek, karena kode ini menjadi lebih jelas. Kelas juga menyediakan fitur tambahan seperti get / set / static

Semua model diletakkan di direktori yang sesuai. Kelas untuk artikel terlihat seperti ini:

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. Implementasi logika bisnis


Tanpa diduga, tetapi pada tahap ini, implementasi logika bisnis itu sendiri TIDAK diperlukan. Anda perlu membuat objek penyimpanan dan segera membaginya menjadi modul:

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, }, }) 


Dan dalam modul itu sendiri, kami akan menjelaskan lebih lanjut semua mutasi / pengambil / tindakan yang digunakan. Awalnya, repositori terlihat seperti ini:

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


Selain itu, kami memulai objek untuk bekerja dengan API yang melaluinya semua permintaan akan berlalu. Pada saat implementasi, bagian depan bagian, backend sama sekali tidak diperlukan, sehingga Anda dapat menggunakan data statis:

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) { //     } }, }; 


Apa yang memberi penggunaan vuex:

  • kemurnian - komponen tidak berubah menjadi benda Tuhan yang "tahu terlalu banyak"
  • konsistensi - jika Anda memiliki beberapa komponen yang menggunakan data yang sama, maka ketika menggunakan wadah vuex saat mengubah data, mereka (data) akan diperbarui di seluruh aplikasi, dan tidak hanya di komponen yang memulai pembaruan
  • kenyamanan - jauh lebih mudah dan lebih mudah untuk mengakses toko daripada menjelaskan jenis parameter dan / atau panggilan API di setiap komponen
  • tes - meskipun siapa yang melakukannya?

5. Menambahkan halaman dan rute


Berdasarkan struktur yang direncanakan sebelumnya, kita perlu membuat 4 halaman: Indeks, Kategori, Artikel, serta 404 halaman. Dalam direktori src / pages, tambahkan file yang sesuai:

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

Jika 404 halaman harus memiliki halaman pribadi dengan desain tersendiri, maka titik masuknya dapat diubah dengan cara ini:

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> 


File halaman utama terlihat seperti ini:

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> 


Setelah implementasi halaman, kami segera menambahkan semua getter dan tindakan yang digunakan ke repositori vuex (tanpa implementasi):

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) {}, }, } 


Ada beberapa hal yang perlu diperhatikan:

  • ketika Anda perlu mendapatkan data, Anda perlu menghubungi negara. Jika, setelah menerima data, Anda perlu melakukan manipulasi data, lebih baik membuat getter untuk ini;
  • ketika Anda perlu melakukan sesuatu dengan data, Anda perlu merujuk ke tindakan, bukan mutasi. Satu tindakan dapat mencakup beberapa mutasi dan melakukan manipulasi data lainnya serta menulis ke negara dan tidak memiliki batasan asinkron
  • Tidak perlu membuat permintaan langsung ke API / Istirahat. Saat meminta semua data melalui Vuex, ini akan menjamin keadaan konsisten dari seluruh aplikasi (jika penyimpanan itu sendiri dilakukan dengan benar)
  • di semua tautan dan navigasi program, Anda perlu merujuk ke rute yang ditentukan. Ini akan memungkinkan Anda mengubah rute sendiri tanpa susah payah tanpa mengedit tautan dan navigasi program. Ini secara alami tentang tautan di dalam SPA, alamat yang tidak diproses oleh router harus ditentukan seperti biasa

Setelah membuat dan mengisi halaman sendiri, Anda perlu menambahkan aturan yang sesuai ke router:

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'), }, ] }) 


Semua parameter router dapat ditemukan di dokumentasi: router.vuejs.org/ru/api/#constructor options-router

6. Menambahkan komponen


Setelah menerapkan semua halaman kami mendapatkan daftar komponen berikut, yang utama:

  • ItemItem
  • Item artikel
  • CommentItem
  • CommentForm

Dan bantu:

  • Daftar item
  • Header

Karena kami menggunakan model, saat menerapkan komponen, kami dapat menggunakannya untuk menentukan parameter:

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> 


Beberapa kata tentang implementasi komponen pada utama:

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> 


Halaman ini menggunakan komponen pembungkus ListItems. Pada pandangan pertama, ini mungkin tampak berlebihan, karena Anda dapat bertahan dengan konstruksi v-for ketika komentar dibuat, tetapi menggunakan slot sangat mengurangi kode yang digunakan dan memungkinkan Anda untuk menggunakan kembali elemen yang sama di beberapa tempat.

Tetapi jika Anda melihat daftar artikel, maka ini digunakan pada dua halaman (Indeks dan Kategori) dengan panggilan yang persis sama. Dalam situasi ini, itu adalah keputusan yang tepat untuk membuat komponen ArticleItems dan mewarisinya dari ListItems:

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> 


Dalam situasi ini, warisan memungkinkan untuk tidak menduplikasi deskripsi parameter (properti props), itu diambil dari komponen induk. Lebih lanjut tentang warisan dan ketidakmurnian: ru.vuejs.org/v2/api/#extends , ru.vuejs.org/v2/guide/mixins.html

Setelah membuat komponen baru, Anda juga perlu memperbaiki file halaman:

src / pages / Category.vue (tadinya)
 <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 (menjadi)
 <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> 


Anda juga perlu memperhatikan formulir untuk menambahkan komentar. Permintaan tidak dibuat langsung ke API, tetapi tindakan Vuex dilakukan dan permintaan ke API sudah "di dalam", model Artikel yang diperlukan diperbarui dan daftar komentar diperbarui. Kode komponen itu sendiri terlihat seperti ini:

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> 


Setelah menerapkan semua komponen dan halaman, menerapkan bertopik dan menambahkan data uji, dalam kasus khusus ini, bagian depan blog siap. Tetapi seperti yang biasanya terjadi dalam praktik, ini masih jauh dari akhir proyek, karena setelah selesai bekerja, perubahan dimulai :-)

7. Suntingan


Misalkan kita perlu mengubah tampilan artikel pada halaman kategori: mereka harus ditampilkan dalam 2 kolom. Dan di halaman utama semuanya harus tetap apa adanya.

Kami menambahkan properti cols tambahan ke jumlah kolom dalam komponen ArticleItems.

src / components / ArticleItems.vue (menjadi)
 <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> 


Di panggilan komponen di halaman kategori, tambahkan properti yang diinginkan:

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


Kemudian kami ingin pergi ke halaman melihat artikel, menambahkan tautan ke artikel tetangga (maju / mundur). Untuk melakukan ini, Anda perlu menambahkan 2 getter dan tautan ke halaman:

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> 


Dan implementasi dari getter itu sendiri:

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; }, ... 


Dan akhirnya, kita perlu mengubah URL untuk halaman artikel, dari "article-123" menjadi "post-123". Karena rute yang dinamai digunakan di seluruh aplikasi, cukup untuk mengubah hanya pola rute:

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'), }, ]; 



Literatur yang bermanfaat


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


PS


Terlepas dari kenyataan bahwa ini ternyata merupakan aplikasi yang sangat sederhana, struktur dibuat sedemikian rupa sehingga Anda dapat dengan mudah mengubah sesuatu dan / atau menambahkan:

  • Komponen menangani secara eksklusif dengan visual, data diambil dari repositori dalam bentuk model, dan permintaan API langsung tidak dibuat.
  • Model berisi logika bisnis yang diperlukan dan semua hubungan antar entitas. Juga JANGAN mengakses API.
  • Penyimpanan (vuex) adalah tautan penghubung semua komponen: data diminta dari API dan dikonversi menjadi model, yang kemudian diakses oleh komponen.

Secara visual, ini dapat direpresentasikan sebagai berikut:


Dengan skema ini, pengerjaan proyek dapat dibagi dengan aman di antara tiga unit:

  • Tn. Tata letak - terlibat dalam implementasi halaman dan komponen, dan juga menjelaskan bidang mana yang harus berisi model, dan pengambil dan tindakan mana yang harus berada dalam repositori;
  • Tn. Front - terlibat dalam implementasi logika bisnis dan model penyimpanan Vuex, serta dalam perutean dan segala sesuatu yang tidak berhubungan dengan tata letak Tn.;
  • Mr. back - terlibat dalam implementasi layanan API di sisi backend.

Semua unit dapat bekerja secara independen satu sama lain jika semua kesamaan di antara mereka telah dibahas sebelumnya (secara umum, jika ada perencanaan sebelum mengerjakan proyek).

Atau jika tidak ada tim seperti itu, adalah logis untuk pergi secara berurutan dari atas ke bawah, sehingga sesegera mungkin ada sesuatu untuk ditonton (roll out MVP).

Repositori dengan semua sumber: github.com/irpsv/vue-blog-habr

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


All Articles