
рд╕рднреА рдХреЛ рдирдорд╕реНрдХрд╛рд░! рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ, рд╣рдо Vuex рдФрд░ Router рд╕рд╣рд┐рдд Vue рдХреЗ рд╕рднреА рдЖрдХрд░реНрд╖рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдХ рд╕рд░рд▓ Vue рдмреНрд▓реЙрдЧ рдХреЗ рд╕рд╛рдордиреЗ рдХреЗ рд╡рд┐рдХрд╛рд╕ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВрдЧреЗред рдФрд░ рдЪрд▓реЛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреА рд╕рдВрд░рдЪрдирд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рднреА рдмрд╛рдд рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдХрдВрдЯреЗрдирд░ рдФрд░ рд░рд╛рдЙрдЯрд░ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВред
рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдо рдЖрд╡реЗрджрди рдХреЗ рд▓рд┐рдП рдореЛрд░реНрдЪрд╛ рдмрдирд╛рдиреЗ рдХреЗ рдЪрд░рдгреЛрдВ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░реЗрдВрдЧреЗ (рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рдмреНрд▓реЙрдЧ):
- рдЖрдпреЛрдЬрди
- рдЖрд╡реЗрджрди рдХрдВрдХрд╛рд▓
- рдореЙрдбрд▓ рдмрдирд╛ рд░рд╣реЗ рд╣реИрдВ
- рд╡реНрдпрд╛рдкрд╛рд░ рддрд░реНрдХ рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди
- рдкреГрд╖реНрдареЛрдВ рдФрд░ рдорд╛рд░реНрдЧреЛрдВ рдХреЛ рдЬреЛрдбрд╝рдирд╛
- рдШрдЯрдХреЛрдВ рдХреЛ рдЬреЛрдбрд╝рдирд╛
- рд╕рдВрдкрд╛рджрд┐рдд рдХрд░реЗрдВ
1. рдпреЛрдЬрдирд╛
рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рд▓рд┐рдЦреЗрдВрдЧреЗ рдХрд┐ рд╣рдорд╛рд░реЗ рдПрд╕рдкреАрдП рдореЗрдВ рдХреНрдпрд╛ рд╣реЛрдЧрд╛ред рдЖрдкрдХреЛ рд╕реАрдзреЗ рдкреГрд╖реНрдареЛрдВ рд╕реЗ рд╢реБрд░реВ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рд╡рд╣реА рд╣реИ рдЬреЛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рд╕рд╛рде рд╕реАрдзреЗ рдЗрдВрдЯрд░реИрдХреНрдЯ рдХрд░рддрд╛ рд╣реИ (рдЕрдЧрд░ рдпрд╣ рдЯреАрдбреАрдбреА рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЗ рд╕рдорд╛рди рдЧреЛрд▓ рдХрд░рдирд╛ рдмрд╣реБрдд рдХрдард┐рди рд╣реИ - рд╣рдо рдкрд╣рд▓реЗ рдпрд╣ рд╡рд░реНрдгрди рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ рдЖрд╡реЗрджрди рдХреНрдпрд╛ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП, рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЗрд╕рдХреЗ рд╕рд╛рде рдХреИрд╕реЗ рдмрд╛рддрдЪреАрдд рдХрд░реЗрдЧрд╛, рдФрд░ рдлрд┐рд░ рд╣рдо рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ рд▓рдЧреЗ рд╣реБрдП рд╣реИрдВ)ред
рддреЛ рдХреНрдпрд╛ рдкреЗрдЬ рд╣реЛрдВрдЧреЗ:
- рд╣реЛрдо - рдЗрд╕рдореЗрдВ рд▓реЛрдХрдкреНрд░рд┐рдп рд╢реНрд░реЗрдгрд┐рдпрд╛рдВ, рд╣рд╛рд▓ рдХреА рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ рдФрд░ рд▓реЗрдЦ рд╢рд╛рдорд┐рд▓ рд╣реЛрдВрдЧреЗ
- рд╢реНрд░реЗрдгреА рдмреНрд░рд╛рдЙрдЬрд╝ рдХрд░реЗрдВ - рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╢реНрд░реЗрдгреА рдХреЗ рд▓рд┐рдП рд▓реЗрдЦреЛрдВ рдХреА рдПрдХ рд╕реВрдЪреАред
- рд╕рдорд╛рдЪрд╛рд░ рджреЗрдЦреЗрдВ - рд╕реАрдзреЗ рд╕рдорд╛рдЪрд╛рд░ рдХреА рд╕рд╛рдордЧреНрд░реА рдФрд░ рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рдХреА рдПрдХ рд╕реВрдЪреА, рдФрд░ рд╢реНрд░реЗрдгреА рдХреЗ рдЕрдиреНрдп рд▓реЗрдЦ
рдпрджрд┐ рдЖрдк рдкреГрд╖реНрдареЛрдВ рдХреЗ рдкреНрд░реЛрдЯреЛрдЯрд╛рдЗрдк рд░рдЦрддреЗ рд╣реИрдВ, рддреЛ рдпрд╣ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ:
рд╕реБрдВрджрд░рддрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреБрдЫ рднреА рд╕реНрдкрд╖реНрдЯ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рд╣реИ рдХрд┐ рдкреНрд░реЛрдЯреЛрдЯрд╛рдЗрдк :-) рдореИрдВ рдЕрднреА рд╕рдордЭрд╛рддрд╛ рд╣реВрдВ рдХрд┐ рдкреНрд░реЛрдЯреЛрдЯрд╛рдЗрдк рд╕реЙрдлрд╝реНрдЯрд╡реЗрдпрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЗрд╕реЗ рдХреНрдпреЛрдВ рдирд╣реАрдВ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ: рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдХрд╛рдЧрдЬ рдкрд░ рдмрд╣реБрдд рддреЗрдЬрд╝ рдФрд░ рдЖрд╕рд╛рди рд╣реИ, рдФрд░ рдХрднреА-рдХрднреА рдЖрдкрдХреЛ рдЕрдкрдиреЗ рд╣рд╛рдереЛрдВ рдХреЛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рдХрдм рдЖрддрд╛ рд╣реИ рдЖрдкрдХреЛ рдХрд╣реАрдВ рди рдХрд╣реАрдВ рдмрд╣реБрдд рджреБрдЦреА рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
рд╣рдореЗрдВ рдорд┐рд▓рдиреЗ рд╡рд╛рд▓реЗ рдкреГрд╖реНрдареЛрдВ рдХреЗ рдЖрдзрд╛рд░ рдкрд░, рд╣рдо рдШрдЯрдХреЛрдВ рдХреЛ рд╕реВрдЪреАрдмрджреНрдз рдХрд░рддреЗ рд╣реИрдВ:
- рд▓реЗрдЦреЛрдВ рдХреА рд╕реВрдЪреА
- рд╢реНрд░реЗрдгреА рд╕реВрдЪреА
- рдЯрд┐рдкреНрдкрдгреА рд╕реВрдЪреА
- рдЯрд┐рдкреНрдкрдгреА рдкреНрд░рдкрддреНрд░
рд╣рдо рдШрдЯрдХреЛрдВ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рджреМрд░рд╛рди рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдШрдЯрдХреЛрдВ рдХреЗ рдЕрдиреБрдХреВрд▓рди рд╕реЗ рдирд┐рдкрдЯреЗрдВрдЧреЗ, рдЗрд╕ рд╕реНрддрд░ рдкрд░ рдпрд╣ рдЖрд╡рд╢реНрдпрдХ рдирд╣реАрдВ рд╣реИред
рдЕрдВрдд рдореЗрдВ, рд╕рднреА рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЗрдВрдЯрд░реИрдХреНрд╢рди рдкреЙрдЗрдВрдЯ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддреЗ рд╣реБрдП, рд╣рдо рдЕрдкрдиреЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рд╕рд╛рд░ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддреЗ рд╣реИрдВ:
- рд▓реЗрдЦ (рд╢реАрд░реНрд╖рдХ, рд╕рд╛рдордЧреНрд░реА, рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рдХреА рд╕реВрдЪреА)
- рд╢реНрд░реЗрдгреА (рд╢реАрд░реНрд╖рдХ, рд╕рдорд╛рдЪрд╛рд░ рд╕реВрдЪреА)
- рдЯрд┐рдкреНрдкрдгреА (рд╕рд╛рдордЧреНрд░реА)
рдпрд╣ рдзреНрдпрд╛рди рд░рдЦрдирд╛ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ рдХрд┐ рд╡реНрдпрд╛рдкрд╛рд░рд┐рдХ рддрд░реНрдХ (рдмреАрдПрд▓) рдХрд╛ рд╕рд╛рд░ рд╡рд░реНрдгрд┐рдд рд╣реИ, рди рдХрд┐ рдЖрдзрд╛рд░ рддрд╛рд▓рд┐рдХрд╛ред рдЬрдм рднрд╛рдЧ рдХреЗ рд╕рд╛рдордиреЗ рдХреЗ рд╣рд┐рд╕реНрд╕реЗ рдХреЛ рд╡рд┐рдХрд╕рд┐рдд рдХрд░рдирд╛ рдФрд░ рдпреЛрдЬрдирд╛ рдмрдирд╛рдирд╛, рдФрд░ рдЕрдзрд┐рдХрд╛рдВрд╢ рдкреАрда (рдХреЗрд╡рд▓ рдбреЗрдЯрд╛ рдкрд░рдд рдХреЛ рдЫреЛрдбрд╝рдХрд░), рдпрд╣ рдмреАрдПрд▓ рд╕рдВрд╕реНрдерд╛рдУрдВ рдХреЗ рд╕рд╛рде рд╕рдВрдЪрд╛рд▓рд┐рдд рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИ, рдФрд░ "рддрд╛рд▓рд┐рдХрд╛рдУрдВ" рдХреЗ рд╕рд╛рде рдирд╣реАрдВред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╕рдВрд╕реНрдерд╛рдУрдВ рдХреЗ рдкрд╛рд╕ рдХреЗрд╡рд▓ рд╡рд╣реА рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП рдЬреЛ рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рднрд╡рд┐рд╖реНрдп рдХреЛ рдЫреВрдирд╛ рдЕрдЪреНрдЫрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдмрд╣реБрдд рдХрдо рд╣реА рдпрд╣ рднрд╡рд┐рд╖реНрдп рдЖрддрд╛ рд╣реИ, рдФрд░ рдорд╛рдорд▓реЗ рдореЗрдВ рдЬрдм рдХреЗрд╡рд▓ рдЙрдкрдпреЛрдЧ рдХреА рдЧрдИ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рд░рдЦреА рдЬрд╛рддреА рд╣реИ рдФрд░ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╕рдВрд░рдЪрдирд╛
рд╡рд┐рд╕реНрддрд╛рд░ рдпреЛрдЧреНрдп рд╣реЛрддреА рд╣реИ, рддреЛ рднрд╡рд┐рд╖реНрдп рдореЗрдВ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдореЗрдВ рдХреЛрдИ рд╕рдорд╕реНрдпрд╛ рдирд╣реАрдВ рд╣реЛрддреА рд╣реИ рдФрд░ рд╡рд░реНрддрдорд╛рди рд╕рдордп рдореЗрдВ рдХреБрдЫ рднреА рдирд╣реАрдВ рд╣реИред
2. рдЖрд╡реЗрджрди рдХрдВрдХрд╛рд▓
рд╣рдо рд╕рдВрд░рдЪрдирд╛ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдЧреЗ рдмрдврд╝рддреЗ рд╣реИрдВред рд╣рдо рдХрдВрд╕реЛрд▓ рдореЗрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХрдорд╛рдВрдб рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рддреЗ рд╣реИрдВ:
npm install -g @vue/cli vue create vue-blog-habr -n -d -m npm cd vue-blog-habr
рдпреЗ рдХрдорд╛рдВрдб рдЙрдкрдпреБрдХреНрдд рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдореЗрдВ vue-blog-habr рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдмрдирд╛рддреЗ рд╣реИрдВред Vue-cli рдФрд░ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЧрдП рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрдзрд┐рдХ рдЬрд╛рдирдХрд╛рд░реА
рдпрд╣рд╛рдВ рдкрд╛рдИ рдЬрд╛ рд╕рдХрддреА рд╣реИ ред
рдФрд░ рдЕрдВрдд рдореЗрдВ рд╣рдореЗрдВ рдорд╛рдирдХ рдкрд░рд┐рдпреЛрдЬрдирд╛ рд╕рдВрд░рдЪрдирд╛ рдорд┐рд▓рддреА рд╣реИ:

рддреБрд░рдВрдд рдЙрди рдкреИрдХреЗрдЬреЛрдВ рдХреЛ рд╕реНрдерд╛рдкрд┐рдд рдХрд░реЗрдВ рдЬрд┐рдирдХреА рд╣рдореЗрдВ рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ:
npm install vue-router vuex axios bootstrap-vue sass-loader npm install --save-dev --unsafe-perm node-sass
рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЧрдП рдореЙрдбреНрдпреВрд▓ рдХреЛ рдкрдВрдЬреАрдХреГрдд рдХрд░реЗрдВ:
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')
рд╣рдо рдЗрд╕ рддрд░рд╣ рд╕реЗ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдбрд╛рдпрд░реЗрдХреНрдЯрд░реА рд╕реНрдЯреНрд░рдХреНрдЪрд░ рдХреЛ рд╕рд╣реА рдХрд░рддреЗ рд╣реИрдВ:

рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рд╡рд┐рд╡рд░рдг:
- рдПрдкреАрдЖрдИ - рдореЗрдВ рд╕рд░реНрд╡рд░ рдХреЗ рд╕рд╛рде "рд╕рдВрдЪрд╛рд░" рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рдлрд╛рдЗрд▓реЗрдВ рд╣реИрдВ
- рд╕рдВрдкрддреНрддрд┐ - рд╡рд┐рднрд┐рдиреНрди рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЧрдП рд╕реНрдерд┐рд░ рд╕рдВрд╕рд╛рдзрди: рдЪрд┐рддреНрд░, рдЖрдЗрдХрди, ...
- рдШрдЯрдХреЛрдВ - рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдШрдЯрдХреЛрдВ, рд░рд╛рдЙрдЯрд░ рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЧрдП "рдкреГрд╖реНрда" рдХреЗ рдмрд┐рдирд╛
- рдореЙрдбрд▓ - рд╡реНрдпрд╛рдкрд╛рд░ рддрд░реНрдХ рдХреЗ рдореЙрдбрд▓, рдЙрдиреНрд╣реЗрдВ рд╕рд╛рдордиреЗ рд╡рд╛рд▓реЗ рдбреЛрдореЗрди рдХреЗ рдХрд╛рд░реНрдпрд╛рддреНрдордХ рдХреЗ рд╕рд╛рде рд╕рдВрддреГрдкреНрдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ
- рдкреЗрдЬ - рд░рд╛рдЙрдЯрд░ рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ рдкреЗрдЬ рдШрдЯрдХ
- рд░рд╛рдЙрдЯрд░ - рд░рд╛рдЙрдЯрд┐рдВрдЧ рдлрд╛рдЗрд▓реЗрдВ
- рд╕реЗрд╡рд╛рдПрдВ - рд╕рд╣рд╛рдпрдХ рд╕реЗрд╡рд╛рдПрдВ рдЬреЛ рд╡реНрдпрд╛рд╡рд╕рд╛рдпрд┐рдХ рддрд░реНрдХ рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рдирд╣реАрдВ рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдкреНрд░рджрд░реНрд╢рди рд╕реЗрд╡рд╛, рдЬрд┐рд╕рдореЗрдВ рдПрдХ рдкреГрд╖реНрда рдкрд░ рдПрдХ рддрддреНрд╡ рдХреЗ рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╡рд┐рдзрд┐ рд╢рд╛рдорд┐рд▓ рд╣реИ
- рд╕реНрдЯреЛрд░ - Vuex рднрдВрдбрд╛рд░рдг рдлрд╝рд╛рдЗрд▓реЗрдВ
- рд╢реИрд▓рд┐рдпреЛрдВ - рд╢реИрд▓реА рдлрд╝рд╛рдЗрд▓реЗрдВ
рдФрд░ рдкрд░реАрдХреНрд╖рдг рд╕рд░реНрд╡рд░ рдЪрд▓рд╛рдПрдВ:
npm run serve
рдЕрдВрддрд┐рдо рдХрдорд╛рдВрдб рд╕рд░реНрд╡рд░ рд╢реБрд░реВ рдХрд░рддрд╛ рд╣реИ рдЬрд┐рд╕ рдкрд░ рд░рдирдЯрд╛рдЗрдо рдореЛрдб рдореЗрдВ рд╕рднреА рдкреНрд░реЛрдЬреЗрдХреНрдЯ рд╕рдВрдкрд╛рджрди рд▓рд╛рдЧреВ рд╣реЛрддреЗ рд╣реИрдВред рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдХреЛ рдПрдХреНрд╕реЗрд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП:
рд▓реЛрдХрд▓рд╣реЛрд╕реНрдЯ : 8080 рдкрд░ рдЬрд╛рдПрдБ
3. рдореЙрдбрд▓ рдмрдирд╛рдирд╛
рд╣рдорд╛рд░реЗ рдЖрд╡реЗрджрди рдореЗрдВ рдХреЛрдИ рдЬрдЯрд┐рд▓ рддрд░реНрдХ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдлрд┐рд░ рднреА, рдЖрдкрдХреЛ рдХрд┐рд╕реА рднреА рдорд╛рдорд▓реЗ рдореЗрдВ рдореЙрдбрд▓ рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
рдЗрд╕рдХреЗ рдХрдИ рдХрд╛рд░рдг рд╣реИрдВ:
- рд╡рд╕реНрддреБрдУрдВ рдХреЗ рд╡рд┐рдирд┐рд░реНрджреЗрд╢ - рдХрд┐рд╕реА рднреА рдордирдорд╛рдиреА рд╡рд╕реНрддреБ, рдореЗрдВ рдХреЛрдИ рднреА рдЧреБрдг рдФрд░ рд╡рд┐рдзрд┐рдпрд╛рдБ рд╣реЛ рд╕рдХрддреА рд╣реИрдВред рдЬрдм рдХрдХреНрд╖рд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рд╣рдо рдЬрд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рдХрд┐рд╕реА рд╡рд┐рд╢реЗрд╖ рд╡рд╕реНрддреБ рдХреЗ рдХреНрдпрд╛ рдЧреБрдг рдФрд░ рддрд░реАрдХреЗ рд╣реИрдВ
- рдШрдЯрдХ рдорд╛рдкрджрдВрдбреЛрдВ рдХреА рдЯрд╛рдЗрдкрд┐рдВрдЧ - рдкрд┐рдЫрд▓реЗ рд╕реЗ рдирд┐рдореНрди рдкреНрд░рдХрд╛рд░: Vue рдШрдЯрдХ рдЗрдирдкреБрдЯ рдЧреБрдгреЛрдВ рдХреЗ рдкреНрд░рдХрд╛рд░ рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░рддреЗ рд╣реИрдВ
- рд╕реБрд╡рд┐рдзрд╛ - рдХрдХреНрд╖рд╛рдУрдВ рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ, рд╣рдо рд╡рд┐рд╖рдп рдХреНрд╖реЗрддреНрд░ рдХреА рд╕рдВрд╕реНрдерд╛рдУрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВ, рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕рд╕реЗ рдХреЛрдб рд╕реНрдкрд╖реНрдЯ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред рдХрдХреНрд╖рд╛рдПрдВ рдЕрддрд┐рд░рд┐рдХреНрдд рд╕реБрд╡рд┐рдзрд╛рдПрдВ рднреА рдкреНрд░рджрд╛рди рдХрд░рддреА рд╣реИрдВ рдЬреИрд╕реЗ рдЧреЗрдЯ / рд╕реЗрдЯ / рд╕реНрдЯреИрдЯрд┐рдХ
рд╕рднреА рдореЙрдбрд▓реЛрдВ рдХреЛ рдЙрдкрдпреБрдХреНрдд рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдореЗрдВ рд░рдЦрд╛ рдЧрдпрд╛ рд╣реИред рд▓реЗрдЦ рдХреЗ рд▓рд┐рдП рд╡рд░реНрдЧ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ:
src / рдореЙрдбрд▓ / 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. рд╡реНрдпрд╛рд╡рд╕рд╛рдпрд┐рдХ рддрд░реНрдХ рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди
рдЕрдкреНрд░рддреНрдпрд╛рд╢рд┐рдд рд░реВрдк рд╕реЗ, рд▓реЗрдХрд┐рди рдЗрд╕ рд╕реНрддрд░ рдкрд░, рд╡реНрдпрд╡рд╕рд╛рдп рддрд░реНрдХ рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╕реНрд╡рдпрдВ рдЖрд╡рд╢реНрдпрдХ рдирд╣реАрдВ рд╣реИред рдЖрдкрдХреЛ рд╕реНрдЯреЛрд░реЗрдЬ рдСрдмреНрдЬреЗрдХреНрдЯ рдмрдирд╛рдиреЗ рдФрд░ рдЙрд╕реЗ рддреБрд░рдВрдд рдореЙрдбреНрдпреВрд▓ рдореЗрдВ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ:
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, }, })
рдФрд░ рдореЙрдбреНрдпреВрд▓ рдореЗрдВ рд╣реА, рд╣рдо рдЖрдЧреЗ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЧрдП рд╕рднреА рдЙрддреНрдкрд░рд┐рд╡рд░реНрддрди / рдЧреЗрдЯрд░реНрд╕ / рдХреНрд░рд┐рдпрд╛рдУрдВ рдХрд╛ рд╡рд░реНрдгрди рдХрд░реЗрдВрдЧреЗред рдкреНрд░рд╛рд░рдВрдн рдореЗрдВ, рднрдВрдбрд╛рд░ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ:
src / store / рдореЙрдбреНрдпреВрд▓ / blog.js export default { state: {}, getters: {}, mutations: {}, actions: {}, }
рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╣рдо рдПрдкреАрдЖрдИ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╡рд╕реНрддреБ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ рдЬрд┐рд╕рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╕рднреА рдЕрдиреБрд░реЛрдз рдкрд╛рд░рд┐рдд рд╣реЛрдВрдЧреЗред рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рд╕рдордп, рднрд╛рдЧ рдХреЗ рд╕рд╛рдордиреЗ, рдмреИрдХрдПрдВрдб рдмрд┐рд▓реНрдХреБрд▓ рдЖрд╡рд╢реНрдпрдХ рдирд╣реАрдВ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЖрдк рд╕реНрдереИрддрд┐рдХ рдбреЗрдЯрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
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) {
рдХреНрдпрд╛ рджреЗрддрд╛ рд╣реИ vuex рдХрд╛ рдЙрдкрдпреЛрдЧ:
- рдкрд╡рд┐рддреНрд░рддрд╛ - рдШрдЯрдХ рдИрд╢реНрд╡рд░ рдХреА рд╡рд╕реНрддреБрдУрдВ рдореЗрдВ рдирд╣реАрдВ рдмрджрд▓рддреЗ рдЬреЛ "рдмрд╣реБрдд рдЬреНрдпрд╛рджрд╛ рдЬрд╛рдирддреЗ рд╣реИрдВ"
- рд╕реНрдерд┐рд░рддрд╛ - рдпрджрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ рдХрдИ рдШрдЯрдХ рд╣реИрдВ рдЬреЛ рд╕рдорд╛рди рдбреЗрдЯрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдбреЗрдЯрд╛ рдмрджрд▓рддреЗ рд╕рдордп vuex рдХрдВрдЯреЗрдирд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╕рдордп, рдЙрдиреНрд╣реЗрдВ (рдбреЗрдЯрд╛) рдкреВрд░реЗ рдЖрд╡реЗрджрди рдореЗрдВ рдЕрдкрдбреЗрдЯ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдФрд░ рди рдХреЗрд╡рд▓ рдЙрд╕ рдШрдЯрдХ рдореЗрдВ, рдЬрд┐рд╕рдиреЗ рдЕрдкрдбреЗрдЯ рд╢реБрд░реВ рдХрд┐рдпрд╛ рдерд╛
- рд╕реБрд╡рд┐рдзрд╛ - рдкреНрд░рддреНрдпреЗрдХ рдШрдЯрдХ рдореЗрдВ рдкреИрд░рд╛рдореАрдЯрд░ рдФрд░ / рдпрд╛ рдПрдкреАрдЖрдИ рдХреЙрд▓ рдХреЗ рдкреНрд░рдХрд╛рд░ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдиреЗ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рд╕реНрдЯреЛрд░ рддрдХ рдкрд╣реБрдВрдЪрдирд╛ рдмрд╣реБрдд рдЖрд╕рд╛рди рдФрд░ рдЕрдзрд┐рдХ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИ
- рдкрд░реАрдХреНрд╖рдг - рд╣рд╛рд▓рд╛рдВрдХрд┐ рдпрд╣ рдХреМрди рдХрд░рддрд╛ рд╣реИ?
5. рдкреГрд╖реНрдареЛрдВ рдФрд░ рдорд╛рд░реНрдЧреЛрдВ рдХреЛ рдЬреЛрдбрд╝рдирд╛
рдкрд╣рд▓реЗ рд╕реЗ рдирд┐рдпреЛрдЬрд┐рдд рд╕рдВрд░рдЪрдирд╛ рдХреЗ рдЖрдзрд╛рд░ рдкрд░, рд╣рдореЗрдВ 4 рдкреГрд╖реНрда рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ: рд╕реВрдЪрдХрд╛рдВрдХ, рд╢реНрд░реЗрдгреА, рдЕрдиреБрдЪреНрдЫреЗрдж, рд╕рд╛рде рд╣реА рд╕рд╛рде 404 рдкреГрд╖реНрдаред Src / Pages рдбрд╛рдпрд░реЗрдХреНрдЯрд░реА рдореЗрдВ рдЙрдкрдпреБрдХреНрдд рдлрд╛рдЗрд▓реЗрдВ рдЬреЛрдбрд╝рддрд╛ рд╣реИ:
- Article.vue
- Category.vue
- Index.vue
- 404.vue
рдпрджрд┐ 404 рдкреГрд╖реНрдареЛрдВ рдореЗрдВ рдПрдХ рд╡реНрдпрдХреНрддрд┐рдЧрдд рдбрд┐рдЬрд╝рд╛рдЗрди рд╡рд╛рд▓рд╛ рд╡реНрдпрдХреНрддрд┐рдЧрдд рдкреГрд╖реНрда рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП, рддреЛ рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐ рдмрд┐рдВрджреБ рдХреЛ рдЗрд╕ рддрд░рд╣ рд╕реЗ рдмрджрд▓рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:
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>
рдореБрдЦреНрдп рдкреГрд╖реНрда рдлрд╝рд╛рдЗрд▓ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд╣реИ:
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>
рдкреГрд╖реНрдареЛрдВ рдХреЗ рд▓рд╛рдЧреВ рд╣реЛрдиреЗ рдХреЗ рдмрд╛рдж, рд╣рдо рддреБрд░рдВрдд рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЧрдП рд╕рднреА рдЧреЗрдЯрд░реНрд╕ рдФрд░ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ vuex рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА (рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рдмрд┐рдирд╛) рдореЗрдВ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ:
src / store / рдореЙрдбреНрдпреВрд▓ / blog.js export default { state: { articles: [], comments: [], categories: [],
рдиреЛрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрдИ рдмрд┐рдВрджреБ рд╣реИрдВ:
- рдЬрдм рдЖрдкрдХреЛ рдбреЗрдЯрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рддреЛ рдЖрдкрдХреЛ рд░рд╛рдЬреНрдп рд╕реЗ рд╕рдВрдкрд░реНрдХ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдпрджрд┐, рдбреЗрдЯрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рдЖрдкрдХреЛ рдбреЗрдЯрд╛ рдХреЗ рдХреБрдЫ рд╣реЗрд░рдлреЗрд░ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рддреЛ рдЗрд╕рдХреЗ рд▓рд┐рдП рдЧреЗрдЯрд░реНрд╕ рдмрдирд╛рдирд╛ рдмреЗрд╣рддрд░ рд╣реИ;
- рдЬрдм рдЖрдкрдХреЛ рдбреЗрдЯрд╛ рдХреЗ рд╕рд╛рде рдХреБрдЫ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рддреЛ рдЖрдкрдХреЛ рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреЛ рд╕рдВрджрд░реНрднрд┐рдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛, рди рдХрд┐ рдЙрддреНрдкрд░рд┐рд╡рд░реНрддрдиред рдПрдХ рдХреНрд░рд┐рдпрд╛ рдореЗрдВ рдХрдИ рдЙрддреНрдкрд░рд┐рд╡рд░реНрддрди рд╢рд╛рдорд┐рд▓ рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЕрдиреНрдп рдбреЗрдЯрд╛ рдЬреЛрдбрд╝рддреЛрдбрд╝ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рд╕рд╛рде рд╣реА рд░рд╛рдЬреНрдп рдХреЛ рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рдкреНрд░рддрд┐рдмрдВрдз рдирд╣реАрдВ рд▓рдЧрд╛ рд╕рдХрддреЗ рд╣реИрдВ
- рдПрдкреАрдЖрдИ / рд░реЗрд╕реНрдЯ рдХреЗ рд▓рд┐рдП рд╕реАрдзреЗ рдЕрдиреБрд░реЛрдз рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред Vuex рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╕рднреА рдбреЗрдЯрд╛ рдХрд╛ рдЕрдиреБрд░реЛрдз рдХрд░рддреЗ рд╕рдордп, рдпрд╣ рд╕рдВрдкреВрд░реНрдг рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреА рд╕реБрд╕рдВрдЧрдд рд╕реНрдерд┐рддрд┐ рдХреА рдЧрд╛рд░рдВрдЯреА рджреЗрдЧрд╛ (рдпрджрд┐ рднрдВрдбрд╛рд░рдг рд╕реНрд╡рдпрдВ рд╕рд╣реА рддрд░реАрдХреЗ рд╕реЗ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ)
- рд╕рднреА рд▓рд┐рдВрдХ рдФрд░ рдкреНрд░реЛрдЧреНрд░рд╛рдо рдиреЗрд╡рд┐рдЧреЗрд╢рди рдореЗрдВ, рдЖрдкрдХреЛ рдирд╛рдорд┐рдд рдорд╛рд░реНрдЧреЛрдВ рдХреЛ рд╕рдВрджрд░реНрднрд┐рдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдпрд╣ рд▓рд┐рдВрдХ рдФрд░ рдкреНрд░реЛрдЧреНрд░рд╛рдо рдиреЗрд╡рд┐рдЧреЗрд╢рди рдХреЛ рд╕рдВрдкрд╛рджрд┐рдд рдХрд┐рдП рдмрд┐рдирд╛ рдЖрдкрдХреЛ рджрд░реНрдж рд░рд╣рд┐рдд рддрд░реАрдХреЗ рд╕реЗ рдорд╛рд░реНрдЧреЛрдВ рдХреЛ рдмрджрд▓рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдЧрд╛ред рдпрд╣ рд╕реНрд╡рд╛рднрд╛рд╡рд┐рдХ рд░реВрдк рд╕реЗ рдПрд╕рдкреАрдП рдХреЗ рд▓рд┐рдВрдХ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╣реИ, рд░рд╛рдЙрдЯрд░ рджреНрд╡рд╛рд░рд╛ рд╕рдВрд╕рд╛рдзрд┐рдд рдирд╣реАрдВ рдХрд┐рдП рдЧрдП рдкрддреЗ рд╣рдореЗрд╢рд╛ рдХреА рддрд░рд╣ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд┐рдП рдЬрд╛рдиреЗ рдЪрд╛рд╣рд┐рдП
рдкреГрд╖реНрдареЛрдВ рдХреЛ рд╕реНрд╡рдпрдВ рдмрдирд╛рдиреЗ рдФрд░ рднрд░рдиреЗ рдХреЗ рдмрд╛рдж, рдЖрдкрдХреЛ рд░рд╛рдЙрдЯрд░ рдХреЗ рд▓рд┐рдП рдЙрдЪрд┐рдд рдирд┐рдпрдо рдЬреЛрдбрд╝рдиреЗ рд╣реЛрдВрдЧреЗ:
src / рд░реВрдЯрд░ / 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'), }, ] })
рд╕рднреА рд░рд╛рдЙрдЯрд░ рдкреИрд░рд╛рдореАрдЯрд░ рдХреЛ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рдореЗрдВ рдкрд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:
рд░рд╛рдКрдЯрд░ .vuejs.org /
ru /
api /
#constructor рд╡рд┐рдХрд▓реНрдк / рд░рд╛рдЙрдЯрд░
6. рдШрдЯрдХ рдЬреЛрдбрд╝рдирд╛
рд╕рднреА рдкреГрд╖реНрдареЛрдВ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рд╣рдореЗрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдШрдЯрдХреЛрдВ рдХреА рд╕реВрдЪреА рдорд┐рд▓рддреА рд╣реИ, рдЬрд┐рдирдореЗрдВ рд╕реЗ рдореБрдЦреНрдп рд╣реИрдВ:
- CategoryItem
- ArticleItem
- CommentItem
- CommentForm
рдФрд░ рд╕рд╣рд╛рдпрдХ:
рдЪреВрдВрдХрд┐ рд╣рдо рдореЙрдбрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рдШрдЯрдХреЛрдВ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╕рдордп, рд╣рдо рдЙрдиреНрд╣реЗрдВ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рдЯрд╛рдЗрдк рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
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>
рдореБрдЦреНрдп рдкрд░ рдШрдЯрдХреЛрдВ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреБрдЫ рд╢рдмреНрдж:
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>
рдпрд╣ рдкреГрд╖реНрда ListItems рдХреЗ рдЖрд╡рд░рдг рдШрдЯрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИред рдкрд╣рд▓реА рдирдЬрд╝рд░ рдореЗрдВ, рдпрд╣ рдирд┐рд░рд░реНрдердХ рд▓рдЧ рд╕рдХрддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдЖрдк рд╡реА-рдлреЙрд░ рдХрдВрд╕реНрдЯреНрд░рдХреНрд╢рди рдХреЗ рд╕рд╛рде рдЯрд┐рдкреНрдкрдгреА рдХреЗ рд░реВрдк рдореЗрдВ рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рд╕реНрд▓реЙрдЯреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЧрдП рдХреЛрдб рдХреЛ рдмрд╣реБрдд рдХрдо рдХрд░ рджреЗрддрд╛ рд╣реИ рдФрд░ рдЖрдкрдХреЛ рдХрдИ рд╕реНрдерд╛рдиреЛрдВ рдкрд░ рдПрдХ рд╣реА рддрддреНрд╡ рдХрд╛ рдкреБрди: рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред
рд▓реЗрдХрд┐рди рдпрджрд┐ рдЖрдк рд▓реЗрдЦреЛрдВ рдХреА рд╕реВрдЪреА рдХреЛ рджреЗрдЦрддреЗ рд╣реИрдВ, рддреЛ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рджреЛ рдкреГрд╖реНрдареЛрдВ (рдЗрдВрдбреЗрдХреНрд╕ рдФрд░ рд╢реНрд░реЗрдгреА) рдкрд░ рдПрдХ рд╣реА рдХреЙрд▓ рдХреЗ рд╕рд╛рде рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ, рдпрд╣ ArticleItems рдШрдЯрдХ рдмрдирд╛рдиреЗ рдФрд░ рдЗрд╕реЗ 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>
рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ, рд╡рдВрд╢рд╛рдиреБрдХреНрд░рдо рдкреИрд░рд╛рдореАрдЯрд░ (рдкреНрд░реЙрдкреНрд╕ рдкреНрд░реЙрдкрд░реНрдЯреА) рдХреЗ рд╡рд┐рд╡рд░рдг рдХреА рдирдХрд▓ рдирд╣реАрдВ рдХрд░рдиреЗ рджреЗрддрд╛ рд╣реИ, рдЗрд╕реЗ рдореВрд▓ рдШрдЯрдХ рд╕реЗ рд▓рд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рд╡рд┐рд░рд╛рд╕рдд рдФрд░ рдЕрд╢реБрджреНрдзрд┐рдпреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрдзрд┐рдХ рдЬрд╛рдирдХрд╛рд░реА:
ru.vuejs.org/v2/api/#extends ,
ru.vuejs.org/v2/guide/mixins.htmlрдПрдХ рдирдпрд╛ рдШрдЯрдХ рдмрдирд╛рдиреЗ рдХреЗ рдмрд╛рдж, рдЖрдкрдХреЛ рдкреГрд╖реНрда рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рднреА рдареАрдХ рдХрд░рдирд╛ рд╣реЛрдЧрд╛:
src / Pages / Category.vue (рдерд╛) <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 (рдмрдиреЗ) <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>
рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдлрд╝реЙрд░реНрдо рдкрд░ рднреА рдзреНрдпрд╛рди рджреЗрдиреЗ рдпреЛрдЧреНрдп рд╣реИред рдЕрдиреБрд░реЛрдз рд╕реАрдзреЗ API рд╕реЗ рдирд╣реАрдВ рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди Vuex рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХреА рдЬрд╛рддреА рд╣реИ рдФрд░ API рдХреЗ рд▓рд┐рдП рдЕрдиреБрд░реЛрдз рдкрд╣рд▓реЗ рд╕реЗ рд╣реА "рдЕрдВрджрд░" рд╣реИ, рдЖрд╡рд╢реНрдпрдХ рдЕрдиреБрдЪреНрдЫреЗрдж рдореЙрдбрд▓ рдЕрдкрдбреЗрдЯ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдФрд░ рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рдХреА рд╕реВрдЪреА рдЕрдкрдбреЗрдЯ рдХреА рдЧрдИ рд╣реИред рдШрдЯрдХ рдХрд╛ рдХреЛрдб рд╕реНрд╡рдпрдВ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ:
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>
рд╕рднреА рдШрдЯрдХреЛрдВ рдФрд░ рдкреГрд╖реНрдареЛрдВ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рд╕реНрдЯрдмреНрд╕ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдФрд░ рдкрд░реАрдХреНрд╖рдг рдбреЗрдЯрд╛ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП, рдЗрд╕ рд╡рд┐рд╢реЗрд╖ рдорд╛рдорд▓реЗ рдореЗрдВ, рдмреНрд▓реЙрдЧ рдХреЗ рд╕рд╛рдордиреЗ рдХрд╛ рд╣рд┐рд╕реНрд╕рд╛ рддреИрдпрд╛рд░ рд╣реИред рд▓реЗрдХрд┐рди рдЬреИрд╕рд╛ рдХрд┐ рдЖрдорддреМрд░ рдкрд░ рд╡реНрдпрд╡рд╣рд╛рд░ рдореЗрдВ рд╣реЛрддрд╛ рд╣реИ, рдпрд╣ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЗ рдЕрдВрдд рд╕реЗ рджреВрд░ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдХрд╛рдо рдкреВрд░рд╛ рд╣реЛрдиреЗ рдХреЗ рдмрд╛рдж, рдкрд░рд┐рд╡рд░реНрддрди рд╢реБрд░реВ рд╣реЛрддреЗ рд╣реИрдВ :-)
7. рд╕рдВрдкрд╛рджрди
рдорд╛рди рд▓реЗрдВ рдХрд┐ рд╣рдореЗрдВ рд╢реНрд░реЗрдгреА рдкреГрд╖реНрда рдкрд░ рд▓реЗрдЦреЛрдВ рдХреЗ рдкреНрд░рджрд░реНрд╢рди рдХреЛ рдмрджрд▓рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ: рдЙрдиреНрд╣реЗрдВ 2 рдХреЙрд▓рдо рдореЗрдВ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рдФрд░ рдореБрдЦреНрдп рдкреГрд╖реНрда рдкрд░ рд╕рдм рдХреБрдЫ рд╡реИрд╕рд╛ рд╣реА рд░рд╣рдирд╛ рдЪрд╛рд╣рд┐рдП рдЬреИрд╕рд╛ рд╡рд╣ рд╣реИред
рд╣рдо ArticleItems рдШрдЯрдХ рдореЗрдВ рд╕реНрддрдВрднреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рдПрдХ рдЕрддрд┐рд░рд┐рдХреНрдд cols рдЧреБрдг рдЬреЛрдбрд╝рддреЗ рд╣реИрдВред
src / Components / ArticleItems.vue (рдмрдиреЗ) <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>
рд╢реНрд░реЗрдгрд┐рдпреЛрдВ рдкреГрд╖реНрда рдкрд░ рдШрдЯрдХ рдХреЙрд▓ рдореЗрдВ, рд╡рд╛рдВрдЫрд┐рдд рд╕рдВрдкрддреНрддрд┐ рдЬреЛрдбрд╝реЗрдВ:
src / Pages / Category.vue <ArticleItems :items="articles" :cols="2"></ArticleItems>
рддрдм рд╣рдо рд▓реЗрдЦ рджреЗрдЦрдиреЗ рдХреЗ рдкреЗрдЬ рдкрд░ рдЬрд╛рдирд╛ рдЪрд╛рд╣рддреЗ рдереЗ, рдкрдбрд╝реЛрд╕реА рд▓реЗрдЦ (рдЖрдЧреЗ / рдкрд┐рдЫрдбрд╝реЗ) рдХреЗ рд▓рд┐рдВрдХ рдЬреЛрдбрд╝ рд░рд╣реЗ рдереЗред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдкреЗрдЬ рдкрд░ 2 рдЧреЗрдЯрд░реНрд╕ рдФрд░ рд▓рд┐рдВрдХ рдЬреЛрдбрд╝рдиреЗ рд╣реЛрдВрдЧреЗ:
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>
рдФрд░ рдЦреБрдж рдЧреЗрдЯрд░реНрд╕ рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди:
src / store / рдореЙрдбреНрдпреВрд▓ / 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; }, ...
рдФрд░ рдЕрдВрдд рдореЗрдВ, рд╣рдореЗрдВ рд▓реЗрдЦ рдкреГрд╖реНрда рдХреЗ рд▓рд┐рдП URL рдХреЛ "рд▓реЗрдЦ -123" рд╕реЗ "рдкреЛрд╕реНрдЯ -123" рдореЗрдВ рдмрджрд▓рдирд╛ рд╣реЛрдЧрд╛ред рдЪреВрдВрдХрд┐ рдирд╛рдорд┐рдд рдорд╛рд░реНрдЧреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдкреВрд░реЗ рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдореЗрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдпрд╣ рдХреЗрд╡рд▓ рдорд╛рд░реНрдЧ рдХрд╛ рдкреИрдЯрд░реНрди рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рд╣реИ:
src / рд░реВрдЯрд░ / рдмреНрд▓реЙрдЧ / 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'), }, ];
рдЙрдкрдпреЛрдЧреА рд╕рд╛рд╣рд┐рддреНрдп
- vuex.vuejs.org/ru/guide
- cli.vuejs.org/ru/guide
- router.vuejs.org/ru
рдкреБрдирд╢реНрдЪ
рдЗрд╕ рддрдереНрдп рдХреЗ рдмрд╛рд╡рдЬреВрдж рдХрд┐ рдпрд╣ рдПрдХ рдмрд╣реБрдд рд╣реА рд╕рд░рд▓ рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдирд┐рдХрд▓рд╛, рд╕рдВрд░рдЪрдирд╛ рдЗрд╕ рддрд░рд╣ рд╕реЗ рдмрдирд╛рдИ рдЧрдИ рд╣реИ рдХрд┐ рдЖрдк рдЖрд╕рд╛рдиреА рд╕реЗ рдХреБрдЫ рдмрджрд▓ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ / рдпрд╛:
- рдШрдЯрдХ рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рд╡рд┐рдЬрд╝реБрдЕрд▓реНрд╕ рдХреЗ рд╕рд╛рде рд╕реМрджрд╛ рдХрд░рддреЗ рд╣реИрдВ, рдбреЗрдЯрд╛ рдореЙрдбрд▓ рдХреЗ рд░реВрдк рдореЗрдВ рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рд╕реЗ рд▓рд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдкреНрд░рддреНрдпрдХреНрд╖ рдПрдкреАрдЖрдИ рдЕрдиреБрд░реЛрдз рдирд╣реАрдВ рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВред
- рдореЙрдбрд▓ рдореЗрдВ рдЖрд╡рд╢реНрдпрдХ рд╡реНрдпрд╛рд╡рд╕рд╛рдпрд┐рдХ рддрд░реНрдХ рдФрд░ рд╕рдВрд╕реНрдерд╛рдУрдВ рдХреЗ рдмреАрдЪ рд╕рднреА рд╕рдВрдмрдВрдз рд╣реИрдВред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛ рдПрдкреАрдЖрдИ рдХрд╛ рдЙрдкрдпреЛрдЧ рди рдХрд░реЗрдВред
- рд╕рдВрдЧреНрд░рд╣рдг (vuex) рд╕рднреА рдШрдЯрдХреЛрдВ рдХреА рдХрдиреЗрдХреНрдЯрд┐рдВрдЧ рд▓рд┐рдВрдХ рд╣реИ: рдбреЗрдЯрд╛ рдПрдкреАрдЖрдИ рд╕реЗ рдЕрдиреБрд░реЛрдз рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдореЙрдбрд▓ рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рд╣реЛрддрд╛ рд╣реИ, рдЬреЛ рддрдм рдШрдЯрдХреЛрдВ рджреНрд╡рд╛рд░рд╛ рдПрдХреНрд╕реЗрд╕ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
рдиреЗрддреНрд░рд╣реАрди, рдпрд╣ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рджрд░реНрд╢рд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:

рдЗрд╕ рдпреЛрдЬрдирд╛ рдХреЗ рд╕рд╛рде, рдкрд░рд┐рдпреЛрдЬрдирд╛ рдкрд░ рдХрд╛рдо рддреАрди рдЗрдХрд╛рдЗрдпреЛрдВ рдХреЗ рдмреАрдЪ рд╕реБрд░рдХреНрд╖рд┐рдд рд░реВрдк рд╕реЗ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:
- рд╢реНрд░реА рд▓реЗрдЖрдЙрдЯ - рдкреГрд╖реНрдареЛрдВ рдФрд░ рдШрдЯрдХреЛрдВ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ рд▓рдЧрд╛ рд╣реБрдЖ рд╣реИ, рдФрд░ рдпрд╣ рднреА рд╡рд░реНрдгрди рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдХрд┐рди рдХреНрд╖реЗрддреНрд░реЛрдВ рдореЗрдВ рдореЙрдбрд▓ рд╢рд╛рдорд┐рд▓ рд╣реЛрдиреЗ рдЪрд╛рд╣рд┐рдП, рдФрд░ рдХреМрди рд╕реЗ рдЧреЗрдЯрд░реНрд╕ рдФрд░ рдХреНрд░рд┐рдпрд╛рдПрдВ рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдореЗрдВ рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдП;
- рд╢реНрд░реА рдлреНрд░рдВрдЯ - рд╡реНрдпрд╛рдкрд╛рд░ рддрд░реНрдХ рдФрд░ Vuex- рднрдВрдбрд╛рд░рдг рдореЙрдбрд▓ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ рд▓рдЧреЗ рд╣реБрдП рд╣реИ, рд╕рд╛рде рд╣реА рд░реВрдЯрд┐рдВрдЧ рдФрд░ рдмрд╛рдХреА рд╕рдм рдХреБрдЫ рдЬреЛ рд╢реНрд░реА рд▓реЗрдЖрдЙрдЯ рдХреА рдЪрд┐рдВрддрд╛ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ;
- рд╢реНрд░реА рдмреИрдХ - рдмреИрдХрдПрдВрдб рдкрд░ рдПрдкреАрдЖрдИ рд╕реЗрд╡рд╛рдУрдВ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ рд▓рдЧрд╛ рд╣реБрдЖ рд╣реИред
рд╕рднреА рдЗрдХрд╛рдЗрдпрд╛рдБ рдПрдХ рджреВрд╕рд░реЗ рд╕реЗ рд╕реНрд╡рддрдВрддреНрд░ рд░реВрдк рд╕реЗ рдХрд╛рдо рдХрд░ рд╕рдХрддреА рд╣реИрдВ рдпрджрд┐ рдЙрдирдХреЗ рдмреАрдЪ рдХреА рд╕рднреА рд╕рд╛рдорд╛рдиреНрдп рдЬрдореАрди рдкрд░ рдкрд╣рд▓реЗ рдЪрд░реНрдЪрд╛ рд╣реЛ рдЪреБрдХреА рд╣реЛ (рд╕рд╛рдорд╛рдиреНрдп рддреМрд░ рдкрд░, рдЕрдЧрд░ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдкрд░ рдХрд╛рдо рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдХреЛрдИ рдпреЛрдЬрдирд╛ рдереА)ред
рдпрд╛ рдпрджрд┐ рдХреЛрдИ рдЖрджреЗрд╢ рдирд╣реАрдВ рд╣реИ, рддреЛ рдКрдкрд░ рд╕реЗ рдиреАрдЪреЗ рддрдХ рдХреНрд░рдо рдореЗрдВ рдЬрд╛рдирд╛ рддрд░реНрдХрд╕рдВрдЧрдд рд╣реИ, рддрд╛рдХрд┐ рдЬрд┐рддрдиреА рдЬрд▓реНрджреА рд╣реЛ рд╕рдХреЗ рдХреБрдЫ рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП (рдПрдорд╡реАрдкреА рдмрд╛рд╣рд░ рд░реЛрд▓)ред
рд╕рднреА рд╕реНрд░реЛрддреЛрдВ рдХреЗ рд╕рд╛рде рднрдВрдбрд╛рд░:
github.com/irpsv/vue-blog-habr