
inb4: рдпрд╣ Vue рдФрд░ рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдЯреНрдпреВрдЯреЛрд░рд┐рдпрд▓ рдХреЗ рд╕рд╛рде рдПрдХ рдирдИ рдкрд░рд┐рдпреЛрдЬрдирд╛ "рд╕реЗрдЯрд┐рдВрдЧ" рдирд╣реАрдВ рд╣реИред рдЖрдЗрдП рдХреБрдЫ рдЧрд╣рд░реЗ рдЧреЛрддрд╛ рд▓рдЧрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдФрд░ рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рд╡рд┐рд╖рдпреЛрдВ рдореЗрдВ!
typescript
рдХрдорд╛рд▓ рд╣реИред Vue
рдХрдорд╛рд▓ рд╣реИред рдЗрд╕рдореЗрдВ рдХреЛрдИ рд╢рдХ рдирд╣реАрдВ, рдХрд┐ рдмрд╣реБрдд рд╕рд╛рд░реЗ рд▓реЛрдЧ рдЙрдиреНрд╣реЗрдВ рдПрдХ рд╕рд╛рде рдмрд╛рдВрдзрдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рддреЗ рд╣реИрдВ ред рд▓реЗрдХрд┐рди, рдЕрд▓рдЧ-рдЕрд▓рдЧ рдХрд╛рд░рдгреЛрдВ рдХреЗ рдХрд╛рд░рдг, рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЕрдкрдиреЗ Vue
рдРрдк рдХреЛ рдЯрд╛рдЗрдк рдХрд░рдирд╛ рдореБрд╢реНрдХрд┐рд▓ рд╣реИред рдЖрдЗрдП рдЬрд╛рдиреЗрдВ рдХрд┐ рдХреНрдпрд╛ рд╕рдорд╕реНрдпрд╛рдПрдВ рд╣реИрдВ рдФрд░ рдЙрдиреНрд╣реЗрдВ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреНрдпрд╛ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ (рдпрд╛ рдХрдо рд╕реЗ рдХрдо рдкреНрд░рднрд╛рд╡ рдХрдо рдХрд░реЗрдВ)ред
TLDR
рд╣рдорд╛рд░реЗ рдкрд╛рд╕ Nuxt
, Vue
, Vuex
, рдФрд░ jest
рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЯрд╛рдЗрдк рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдмрд╕ рдЗрд╕реЗ рд╕реНрдерд╛рдкрд┐рдд рдХрд░реЗрдВ рдФрд░ рд╕рдм рдХреБрдЫ рдЖрдкрдХреЗ рд▓рд┐рдП рдХрд╡рд░ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдЕрдзрд┐рдХ рдЬрд╛рдирдиреЗ рдХреЗ рд▓рд┐рдП рдбреЙрдХреНрд╕ рдкрд░ рдЬрд╛рдПрдВред
рдФрд░ рдЬреИрд╕рд╛ рдХрд┐ рдореИрдВрдиреЗ рдХрд╣рд╛ рдХрд┐ рдореИрдВ рддреАрди рдХрд╛рд░рдгреЛрдВ рд╕реЗ рдореВрд▓ рд╕реЗрдЯрдЕрдк рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЖрдкрдХрд╛ рдорд╛рд░реНрдЧрджрд░реНрд╢рди рдХрд░рдиреЗ рд╡рд╛рд▓рд╛ рдирд╣реАрдВ рд╣реВрдВ:
- рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╣реБрдд рд╕рд╛рд░реЗ рдореМрдЬреВрджрд╛ рдЯреНрдпреВрдЯреЛрд░рд┐рдпрд▓ рд╣реИрдВ
- рдПрдХ рдХреНрд▓рд┐рдХ рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рд╕рд╛рд░реЗ рдЙрдкрдХрд░рдг рд╣реИрдВ рдЬреИрд╕реЗ
Nuxt
рдкреНрд▓рдЧрдЗрди рдХреЗ рд╕рд╛рде Nuxt
рдФрд░ vue-cli
- рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА
wemake-vue-template
рдЬрд╣рд╛рдВ рд╣рд░ рд╕реЗрдЯрдЕрдк рдЬреЛ рдореИрдВ рдмрд╛рдд рдХрд░рдиреЗ рдЬрд╛ рд░рд╣рд╛ рд╣реВрдВ рд╡рд╣ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдХрд╡рд░ рд╣реИ
рдШрдЯрдХ рдЯрд╛рдЗрдкрд┐рдВрдЧ
рдЬрдм рдЖрдк Vue
рдФрд░ typescript
рд╕рд╛рде рдХрд╛рдо рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдЖрдкрдХреЗ рджреНрд╡рд╛рд░рд╛ рдЕрдкрдиреЗ рдХрдХреНрд╖рд╛ рдХреЗ рдШрдЯрдХреЛрдВ рдХреЛ рдЯрд╛рдЗрдк рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж рдкрд╣рд▓реА рдЯреВрдЯреА рд╣реБрдИ рдЕрдкреЗрдХреНрд╖рд╛ рдпрд╣ рд╣реИ рдХрд┐ <template>
рдФрд░ <style>
рдЯреИрдЧ рдЕрднреА рднреА рдЯрд╛рдЗрдк рдирд╣реАрдВ рдХрд┐рдП рдЧрдП рд╣реИрдВред рдореИрдВ рдЖрдкрдХреЛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рджрд┐рдЦрд╛рддрд╛ рд╣реВрдВ:
<template> <h1 :class="$style.headr"> Hello, {{ usr }}! </h1> </template> <script lang="ts"> import Vue from 'vue' import Component from 'vue-class-component' import { Prop } from 'vue-property-decorator' @Component({}) export default class HelloComponent extends Vue { @Prop() user!: string } </script> <style module> .header { /* ... */ } </style>
рдореИрдВрдиреЗ рдпрд╣рд╛рдБ рджреЛ рдЯрд╛рдЗрдкреЛ рдмрдирд╛рдП рд╣реИрдВ: {{ usr }}
рдмрдЬрд╛рдп {{ user }}
рдФрд░ $style.headr
рдмрдЬрд╛рдп $style.header
ред рдХреНрдпрд╛ typescript
рдореБрдЭреЗ рдЗрди рддреНрд░реБрдЯрд┐рдпреЛрдВ рд╕реЗ рдмрдЪрд╛рдПрдЧрд╛? рдирд╣реАрдВ, рдпрд╣ рдирд╣реАрдВ рд╣реЛрдЧрд╛ред
рдЗрд╕реЗ рдареАрдХ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреНрдпрд╛ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ? рд╡реИрд╕реЗ, рдХрдИ рд╣реИрдХ рд╣реИрдВред
рдЯреЗрдореНрдкрд▓реЗрдЯ рдЯрд╛рдЗрдк рдХрд░рдирд╛
рдЕрдкрдиреЗ рдЯреЗрдореНрдкреНрд▓реЗрдЯ рдЯрд╛рдЗрдк рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП vetur.experimental.templateInterpolationService
рд╡рд┐рдХрд▓реНрдк рдХреЗ рд╕рд╛рде vetur.experimental.templateInterpolationService
рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рд╣рд╛рдВ, рдпрд╣ рдХреЗрд╡рд▓ рдПрдХ рд╕рдВрдкрд╛рджрдХ-рдЖрдзрд╛рд░рд┐рдд рдЬрд╛рдВрдЪ рд╣реИ рдФрд░ рдЗрд╕реЗ CI рдХреЗ рдЕрдВрджрд░ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рд▓реЗрдХрд┐рди, Vetur
рдЯреАрдо рдЗрд╕реЗ рдЕрдиреБрдорддрд┐ рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП рд╕реАрдПрд▓рдЖрдИ рдкреНрд░рджрд╛рди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрдбрд╝реА рдореЗрд╣рдирдд рдХрд░ рд░рд╣реА рд╣реИред рдЖрдкрдХреА рд░реБрдЪрд┐ рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдореВрд▓ рдореБрджреНрджреЗ рдХреЛ рдЯреНрд░реИрдХ рдХрд░реЗрдВ ред

рджреВрд╕рд░рд╛ рд╡рд┐рдХрд▓реНрдк рджреЛ рд▓реЗрдЦрди рд╕реНрдиреИрдкрд╢реЙрдЯ рдкрд░реАрдХреНрд╖рдг рд╣реИ рдЬрд┐рд╕рдореЗрдВ jest
ред рдпрд╣ рдмрд╣реБрдд рд╕рд╛рд░реЗ рдЯреЗрдореНрдкрд▓реЗрдЯ-рдЖрдзрд╛рд░рд┐рдд рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рдкрдХрдбрд╝ рд▓реЗрдЧрд╛ред рдФрд░ рдпрд╣ рд░рдЦрд░рдЦрд╛рд╡ рдореЗрдВ рдХрд╛рдлреА рд╕рд╕реНрддрд╛ рд╣реИред
рддреЛ, рдЗрди рджреЛ рдЙрдкрдХрд░рдгреЛрдВ рдХрд╛ рд╕рдВрдпреЛрдЬрди рдЖрдкрдХреЛ рддреЗрдЬреА рд╕реЗ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреЗ рд╕рд╛рде рдПрдХ рдЕрдЪреНрдЫрд╛ рдбреЗрд╡рд▓рдкрд░ рдЕрдиреБрднрд╡ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ рдФрд░ рд╕реАрдЖрдИ рдХреЗ рдЕрдВрджрд░ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рдкрдХрдбрд╝рдиреЗ рдХрд╛ рдПрдХ рд╡рд┐рд╢реНрд╡рд╕рдиреАрдп рддрд░реАрдХрд╛ рд╣реИред
рдЯрд╛рдЗрдкрд┐рдВрдЧ рд╕реНрдЯрд╛рдЗрд▓
рдЯрд╛рдЗрдкрд┐рдВрдЧ css-module
рдПрд╕ рднреА рдХрдИ рдмрд╛рд╣рд░реА рдЙрдкрдХрд░рдгреЛрдВ рджреНрд╡рд╛рд░рд╛ рдХрд╡рд░ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ:
рдЗрди рдЙрдкрдХрд░рдгреЛрдВ рдХрд╛ рдореБрдЦреНрдп рд╡рд┐рдЪрд╛рд░ css-module
рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рд╣реИ рдФрд░ рдлрд┐рд░ рдЙрдирдореЗрдВ рд╕реЗ .d.ts
рдШреЛрд╖рдгрд╛ рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рдмрдирд╛рдирд╛ рд╣реИред рдлрд┐рд░ рдЖрдкрдХреА рд╢реИрд▓рд┐рдпреЛрдВ рдХреЛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЯрд╛рдЗрдк рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдпрд╣ рдЕрднреА рднреА Nuxt
рдпрд╛ Vue
рд▓рд┐рдП рд▓рд╛рдЧреВ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЖрдк рдкреНрд░рдЧрддрд┐ рдХреЗ рд▓рд┐рдП рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ Nuxt
рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рд╣рд╛рд▓рд╛рдБрдХрд┐, рдореИрдВ рд╡реНрдпрдХреНрддрд┐рдЧрдд рд░реВрдк рд╕реЗ рдЕрдкрдиреА рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдореЗрдВ рдЗрдирдореЗрдВ рд╕реЗ рдХрд┐рд╕реА рднреА рдЙрдкрдХрд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реВрдВред рд╡реЗ рдмрдбрд╝реЗ рдХреЛрдб рдмреЗрд╕ рдФрд░ рдмрд╣реБрдд рд╕рд╛рд░реА рд╢реИрд▓рд┐рдпреЛрдВ рд╡рд╛рд▓реА рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧреА рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдореИрдВ рд╕рд┐рд░реНрдл рд╕реНрдиреИрдкрд╢реЙрдЯ рдХреЗ рд╕рд╛рде рдареАрдХ рд╣реВрдВред
рджреГрд╢реНрдп рдкреНрд░рддрд┐рдЧрдорди рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЗ рд╕рд╛рде рд╕реНрдЯрд╛рдЗрд▓рдЧрд╛рдЗрдбреНрд╕ рднреА рдмрд╣реБрдд рдорджрдж рдХрд░рддреЗ рд╣реИрдВред @storybook/addon-storyshots
рдЗрд╕ рддрдХрдиреАрдХ рдХрд╛ рдПрдХ рдЕрдЪреНрдЫрд╛ рдЙрджрд╛рд╣рд░рдг рд╣реИред
Vuex
рдЕрдЧрд▓реА рдмрдбрд╝реА рдЪреАрдЬ Vuex
ред рдЯрд╛рдЗрдкрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рдЗрд╕рдореЗрдВ рдХреБрдЫ рдмрд┐рд▓реНрдЯ-рдЗрди-рдбрд┐рдЬрд╝рд╛рдЗрди рдЬрдЯрд┐рд▓рддрд╛ рд╣реИ:
const result: Promise<number> = this.$store.dispatch('action_name', { payload: 1 })
рд╕рдорд╕реНрдпрд╛ рдпрд╣ рд╣реИ рдХрд┐ 'action_name'
рдореМрдЬреВрдж рдирд╣реАрдВ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рдЕрдиреНрдп рддрд░реНрдХ рд▓реЗ рд╕рдХрддрд╛ рд╣реИ рдпрд╛ рдПрдХ рдЕрд▓рдЧ рдкреНрд░рдХрд╛рд░ рд▓реМрдЯрд╛ рд╕рдХрддрд╛ рд╣реИред рдпрд╣ рд╡рд╣ рдЪреАрдЬ рдирд╣реАрдВ рд╣реИ рдЬрд┐рд╕рдХреА рдЖрдк рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЯрд╛рдЗрдк рдХрд┐рдП рдЧрдП рдРрдк рдХреЗ рд▓рд┐рдП рдЙрдореНрдореАрдж рдХрд░рддреЗ рд╣реИрдВред
рдореМрдЬреВрджрд╛ рд╕рдорд╛рдзрд╛рди рдХреНрдпрд╛ рд╣реИрдВ?
vuex рд╢реНрд░реЗрдгреА
vuex-class
рдбреЗрдХреЛрд░реЗрдЯрд░ рдХрд╛ рдПрдХ рд╕реЗрдЯ рд╣реИ рдЬреЛ рдЖрдкрдХреЗ рд╡рд░реНрдЧ-рдЖрдзрд╛рд░рд┐рдд рдШрдЯрдХреЛрдВ рд╕реЗ Vuex
рдЗрдВрдЯрд░реНрдирд▓ рддрдХ рдЖрд╕рд╛рди рдкрд╣реБрдБрдЪ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред
рд▓реЗрдХрд┐рди, рдпрд╣ рд╕реБрд░рдХреНрд╖рд┐рдд рдирд╣реАрдВ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рд░рд╛рдЬреНрдп, рдЧреЗрдЯрд░реНрд╕, рдореНрдпреВрдЯреЗрд╢рди рдФрд░ рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рдкреНрд░рдХрд╛рд░реЛрдВ рдореЗрдВ рд╣рд╕реНрддрдХреНрд╖реЗрдк рдирд╣реАрдВ рдХрд░ рд╕рдХрддрд╛ рд╣реИред

рдмреЗрд╢рдХ, рдЖрдк рдореИрдиреНрдпреБрдЕрд▓ рдкреНрд░рдХрд╛рд░ рдХреА рд╕рдВрдкрддреНрддрд┐рдпреЛрдВ рдХреЛ рдПрдиреЛрдЯреЗрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

рд▓реЗрдХрд┐рди рдЬрдм рдЖрдк рдЕрдкрдиреЗ рд░рд╛рдЬреНрдп рдХреЗ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдкреНрд░рдХрд╛рд░, рдЧреЗрдЯрд░реНрд╕, рдореНрдпреВрдЯреЗрд╢рди рдпрд╛ рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреЛ рдмрджрд▓реЗрдВрдЧреЗ, рддреЛ рдЖрдк рдХреНрдпрд╛ рдХрд░рдиреЗ рдЬрд╛ рд░рд╣реЗ рд╣реИрдВ? рдЖрдкрдХреЗ рдкрд╛рд╕ рдПрдХ рдЫрд┐рдкреЗ рд╣реБрдП рдкреНрд░рдХрд╛рд░ рдХрд╛ рдмреЗрдореЗрд▓ рд╣реЛрдЧрд╛ред
vuex-рд╕рд░рд▓
vuex-simple
рд╣рдорд╛рд░реА рдорджрдж рдХрд░рддрд╛ рд╣реИред рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЖрдкрдХреЗ Vuex
рдХреЛрдб рдХреЛ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЕрд▓рдЧ рддрд░реАрдХрд╛ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ рдФрд░ рдпрд╣реА рдЗрд╕реЗ рд╕реБрд░рдХреНрд╖рд┐рдд рдмрдирд╛рддрд╛ рд╣реИред рдЖрдЗрдП рдирдЬрд░ рдбрд╛рд▓рддреЗ рд╣реИрдВ:
import { Action, Mutation, State, Getter } from 'vuex-simple' class MyStore { // State @State() public comments: CommentType[] = [] // Getters @Getter() public get hasComments (): boolean { return Boolean(this.comments && this.comments.length > 0) } // Mutations @Mutation() public setComments (payload: CommentType[]): void { this.comments = updatedComments } // Actions @Action() public async fetchComments (): Promise<CommentType[]> { // Calling some API: const commentsList = await api.fetchComments() this.setComments(commentsList) // typed mutation return commentsList } }
рдмрд╛рдж рдореЗрдВ рдЗрд╕ рдЯрд╛рдЗрдк рдХрд┐рдП рдЧрдП рдореЙрдбреНрдпреВрд▓ рдХреЛ рдЖрдкрдХреЗ Vuex
рдЕрдВрджрд░ рдкрдВрдЬреАрдХреГрдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдЬреИрд╕реЗ:
import Vue from 'vue' import Vuex from 'vuex' import { createVuexStore } from 'vuex-simple' import { MyStore } from './store' Vue.use(Vuex) // Creates our typed module instance: const instance = new MyStore() // Returns valid Vuex.Store instance: export default createVuexStore(instance)
рдЕрдм рд╣рдорд╛рд░реЗ рдкрд╛рд╕ 100% рджреЗрд╢реА Vuex.Store
рдЙрджрд╛рд╣рд░рдг рдФрд░ рдЗрд╕рдХреЗ рд╕рд╛рде рдмрдВрдбрд▓ рдХреА рдЧрдИ рд╕рднреА рдкреНрд░рдХрд╛рд░ рдХреА рдЬрд╛рдирдХрд╛рд░реАред рдШрдЯрдХ рдореЗрдВ рдЗрд╕ рдЯрд╛рдЗрдк рдХрд┐рдП рдЧрдП рд╕реНрдЯреЛрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣рдо рдХреЛрдб рдХреА рд╕рд┐рд░реНрдл рдПрдХ рдкрдВрдХреНрддрд┐ рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВ:
import Vue from 'vue' import Component from 'nuxt-class-component' import { useStore } from 'vuex-simple' import MyStore from './store' @Component({}) export default class MyComponent extends Vue { // That's all we need! typedStore: MyStore = useStore(this.$store) // Demo: will be typed as `Comment[]`: comments = typedStore.comments }
рдЕрдм рд╣рдордиреЗ Vuex
рдЯрд╛рдЗрдк рдХрд┐рдпрд╛ рд╣реИ Vuex
рд╣рдорд╛рд░реЗ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХреЗ рдЕрдВрджрд░ рд╕реБрд░рдХреНрд╖рд┐рдд рд░реВрдк рд╕реЗ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
рдЬрдм рд╣рдо рдЕрдкрдиреЗ рд╕реНрдЯреЛрд░ рдХреА рдкрд░рд┐рднрд╛рд╖рд╛ рдХреЗ рдЕрдВрджрд░ рдХреБрдЫ рдмрджрд▓рддреЗ рд╣реИрдВ рддреЛ рдпрд╣ рдЙрди рдШрдЯрдХреЛрдВ рдХреЗ рд▓рд┐рдП рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдкрд░рд┐рд▓рдХреНрд╖рд┐рдд рд╣реЛрддрд╛ рд╣реИ рдЬреЛ рдЗрд╕ рд╕реНрдЯреЛрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред рдпрджрд┐ рдХреБрдЫ рд╡рд┐рдлрд▓ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ - рд╣рдо рдЗрд╕реЗ рдЬрд▓реНрдж рд╕реЗ рдЬрд▓реНрдж рдЬрд╛рдирддреЗ рд╣реИрдВред
рдЕрд▓рдЧ-рдЕрд▓рдЧ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рднреА рд╣реИрдВ рдЬреЛ рд╕рдорд╛рди рд╣реИрдВ рд▓реЗрдХрд┐рди рдЙрдирдХреЗ рдкрд╛рд╕ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдПрдкреАрдЖрдИ рд╣реИрдВред рдЪреБрдиреЗрдВ рдХрд┐ рдЖрдкрдХреЛ рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рдХреНрдпрд╛ рд╕реВрдЯ рдХрд░рддрд╛ рд╣реИред
рдПрдкреАрдЖрдИ рдХреЙрд▓
рдЬрдм рд╣рдорд╛рд░реЗ рдкрд╛рд╕ Vuex
рд╕рд╣реА рдврдВрдЧ рд╕реЗ рд╕реЗрдЯрдЕрдк рд╣реЛрддрд╛ рд╣реИ, рддреЛ рд╣рдореЗрдВ рдЗрд╕реЗ рдбреЗрдЯрд╛ рд╕реЗ рднрд░рдирд╛ рд╣реЛрдЧрд╛ред
рдЖрдЗрдП рдПрдХ рдмрд╛рд░ рдлрд┐рд░ рд╣рдорд╛рд░реА рдХреНрд░рд┐рдпрд╛ рдкрд░рд┐рднрд╛рд╖рд╛ рдкрд░ рдирдЬрд╝рд░ рдбрд╛рд▓реЗрдВ:
@Action() public async fetchComments (): Promise<CommentType[]> { // Calling some API: const commentsList = await api.fetchComments() // ... return commentsList }
рд╣рдо рдпрд╣ рдХреИрд╕реЗ рдЬрд╛рди рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ CommentType
рд╕реВрдЪреА CommentType
рдФрд░ рдПрдХ рднреА number
рдпрд╛ AuthorType
рдЗрдВрд╕реНрдЯреЗрдВрд╕ рдХрд╛ рдПрдХ рдЧреБрдЪреНрдЫрд╛ рдирд╣реАрдВ рд╣реЛрдЧрд╛?
рд╣рдо рд╕рд░реНрд╡рд░ рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗред рдФрд░ рд╕рд░реНрд╡рд░ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЕрдиреБрдмрдВрдз рдХреЛ рддреЛрдбрд╝ рд╕рдХрддрд╛ рд╣реИред рдпрд╛ рд╣рдо рдмрд╕ рдЧрд▓рдд api
рдЙрджрд╛рд╣рд░рдг рдХреЛ рдкрд╛рд░рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, URL рдореЗрдВ рдЯрд╛рдЗрдкреЛ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ рдпрд╛ рдЬреЛ рднреА рд╣реЛред
рд╣рдо рдХреИрд╕реЗ рд╕реБрд░рдХреНрд╖рд┐рдд рд░рд╣ рд╕рдХрддреЗ рд╣реИрдВ? рд╣рдо рд░рдирдЯрд╛рдЗрдо рдЯрд╛рдЗрдкрд┐рдВрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ! рдореБрдЭреЗ рдЖрдк рдХреЗ рд▓рд┐рдП io-ts
рдкрд░рд┐рдЪрдп:
import * as ts from 'io-ts' export const Comment = ts.type({ 'id': ts.number, 'body': ts.string, 'email': ts.string, }) // Static TypeScript type, that can be used as a regular `type`: export type CommentType = ts.TypeOf<typeof Comment>
рд╣рдо рдпрд╣рд╛рдБ рдХреНрдпрд╛ рдХрд░рддреЗ рд╣реИрдВ?
- рдЬрдм рд╣рдо рд╕рд░реНрд╡рд░ рд╕реЗ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд╣рдо рдЙрди рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЗ рд╕рд╛рде
ts.type
рдХреА рдПрдХ рдЖрд╡реГрддреНрддрд┐ рдХреЛ ts.type
рдХрд░рддреЗ рд╣реИрдВ, рдЬрд┐рдиреНрд╣реЗрдВ рд╣рдореЗрдВ рд░рдирдЯрд╛рдЗрдо рдореЗрдВ ts.type
рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ - рд╣рдо рдХрд┐рд╕реА рднреА рдЕрддрд┐рд░рд┐рдХреНрдд рдмреЙрдпрд▓рд░рдкреНрд▓реЗрдЯ рдХреЗ рдмрд┐рдирд╛ рдПрдиреЛрдЯреЗрд╢рди рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ рдПрдХ рд╕реНрдерд┐рд░ рдкреНрд░рдХрд╛рд░ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВ
рдФрд░ рдмрд╛рдж рдореЗрдВ рд╣рдо рдЗрд╕реЗ рдЕрдкрдиреЗ api
рдХреЙрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
import * as ts from 'io-ts' import * as tPromise from 'io-ts-promise' public async fetchComments (): Promise<CommentType[]> { const response = await axios.get('comments') return tPromise.decode(ts.array(Comment), response.data) }
io-ts-promise
рдХреА рдорджрдж рд╕реЗ, рд╣рдо рдПрдХ рд╡рд┐рдлрд▓ рд╕реНрдерд┐рддрд┐ рдореЗрдВ рдПрдХ Promise
рд╡рд╛рдкрд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдпрджрд┐ рд╕рд░реНрд╡рд░ рд╕реЗ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдПрдХ ts.array(Comment)
рдкреНрд░рдХрд╛рд░ рд╕реЗ рдореЗрд▓ рдирд╣реАрдВ рдЦрд╛рддреА рд╣реИред рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдПрдХ рд╕рддреНрдпрд╛рдкрди рдХреА рддрд░рд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред
fetchComments() .then((data) => /* ... */ .catch(/* Happens with both request failure and incorrect response type */)
рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╡рд╛рдкрд╕реА рдкреНрд░рдХрд╛рд░ рдПрдиреЛрдЯреЗрд╢рди .decode
рд╡рд┐рдзрд┐ рдХреЗ рд╕рд╛рде рд╕рд┐рдВрдХ рдореЗрдВ рд╣реИред рдФрд░ рдЖрдк рд╡рд╣рд╛рдБ рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рдмрдХрд╡рд╛рд╕ рдирд╣реАрдВ рдбрд╛рд▓ рд╕рдХрддреЗ рд╣реИрдВ:

рд░рдирдЯрд╛рдЗрдо рдФрд░ рд╕реНрдЯреИрдЯрд┐рдХ рдЪреЗрдХ рдХреЗ рд╕рдВрдпреЛрдЬрди рд╕реЗ, рд╣рдо рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдЯрд╛рдЗрдк рдмреЗрдореЗрд▓ рдХреЗ рдХрд╛рд░рдг рд╣рдорд╛рд░реЗ рдЕрдиреБрд░реЛрдз рд╡рд┐рдлрд▓ рдирд╣реАрдВ рд╣реЛрдВрдЧреЗред
рд▓реЗрдХрд┐рди, 100% рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ рд╕рдм рдХреБрдЫ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рдореИрдВ рдЕрдиреБрдмрдВрдз-рдЖрдзрд╛рд░рд┐рдд рдкрд░реАрдХреНрд╖рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рд╕рд┐рдлрд╛рд░рд┐рд╢ рдХрд░реВрдВрдЧрд╛: рдПрдХ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд░реВрдк рдореЗрдВ pact
рдкрд░ рдПрдХ рдирдЬрд╝рд░ рдбрд╛рд▓реЗрдВред рдФрд░ Sentry
рд╕рд╛рде рдЕрдкрдиреЗ рдРрдк рдХреЛ рдореЙрдирд┐рдЯрд░ рдХрд░реЗрдВред
рд╡рд╛рдЙ рд░рд╛рдЙрдЯрд░
рдЕрдЧрд▓реА рд╕рдорд╕реНрдпрд╛ рдпрд╣ рд╣реИ рдХрд┐ this.$router.push({ name: 'wrong!' })
рдЙрд╕ рддрд░реАрдХреЗ рд╕реЗ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ рдЬреИрд╕рд╛ рд╣рдо рдЪрд╛рд╣рддреЗ рд╣реИрдВред
рдореИрдВ рдХрд╣реВрдВрдЧрд╛ рдХрд┐ рд╕рдВрдХрд▓рдХ рджреНрд╡рд╛рд░рд╛ рдЪреЗрддрд╛рд╡рдиреА рджреА рдЬрд╛рдирд╛ рдЖрджрд░реНрд╢ рд╣реЛрдЧрд╛ рдХрд┐ рд╣рдо рдЧрд▓рдд рджрд┐рд╢рд╛ рдореЗрдВ рдЬрд╛ рд░рд╣реЗ рд╣реИрдВ рдФрд░ рдпрд╣ рдорд╛рд░реНрдЧ рдореМрдЬреВрдж рдирд╣реАрдВ рд╣реИред
рд▓реЗрдХрд┐рди, рдпрд╣ рд╕рдВрднрд╡ рдирд╣реАрдВ рд╣реИред рдФрд░ рдмрд╣реБрдд рдХреБрдЫ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ: рдмрд╣реБрдд рд╕рд╛рд░реЗ рдЧрддрд┐рд╢реАрд▓ рдорд╛рд░реНрдЧ рд╣реИрдВ, рд░реЗрдЧреЗрдХреНрд╕, рдлрд╛рд▓рдмреИрдХ, рдЕрдиреБрдорддрд┐рдпрд╛рдВ, рдЖрджрд┐ рдЬреЛ рдЕрдВрддрддрдГ рдЯреВрдЯ рд╕рдХрддреЗ рд╣реИрдВред рдПрдХрдорд╛рддреНрд░ рд╡рд┐рдХрд▓реНрдк рдпрд╣ рд╣реИ рдХрд┐ рдкреНрд░рддреНрдпреЗрдХ рдЖрдкрдХреЗ рдРрдк рдореЗрдВ this.$router
рдХреЙрд▓ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░реЗрдВред
Vue рдкрд░реАрдХреНрд╖рдг-utils
рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмреЛрд▓рддреЗ рд╣реБрдП, рдореЗрд░реЗ рдкрд╛рд╕ @vue/test-utils
рдХрд╛ рдЙрд▓реНрд▓реЗрдЦ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреЛрдИ рдмрд╣рд╛рдирд╛ рдирд╣реАрдВ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдЯрд╛рдЗрдкрд┐рдВрдЧ рдХреЗ рд╕рд╛рде рдХреБрдЫ рд╕рдорд╕реНрдпрд╛рдПрдВ рднреА рд╣реИрдВред
рдЬрдм рд╣рдо typedStore
рд╕рдВрдкрддреНрддрд┐ рдХреЗ рд╕рд╛рде рдЕрдкрдиреЗ рдирдП рдЪрдордХрджрд╛рд░ рдШрдЯрдХ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВрдЧреЗ, рддреЛ рд╣рдо рдкрд╛рдПрдВрдЧреЗ рдХрд┐ рд╣рдо рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ typescript
рдЕрдиреБрд╕рд╛рд░ рдРрд╕рд╛ рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:

рдРрд╕рд╛ рдХреНрдпреЛрдВ рд╣реЛрддрд╛ рд╣реИ? рдРрд╕рд╛ рдЗрд╕рд▓рд┐рдП рд╣реЛрддрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ mount()
рдХреЙрд▓ рдЖрдкрдХреЗ рдШрдЯрдХ рдХреЗ рдкреНрд░рдХрд╛рд░ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреБрдЫ рднреА рдирд╣реАрдВ рдЬрд╛рдирддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рд╕рднреА рдШрдЯрдХреЛрдВ рдореЗрдВ рдПрдХ VueConstructor<Vue>
рдкреНрд░рдХрд╛рд░ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ рд╣реЛрддрд╛ рд╣реИ:

рдпрд╣реАрдВ рд╕реЗ рд╕рд╛рд░реА рд╕рдорд╕реНрдпрд╛рдПрдВ рдЖрддреА рд╣реИрдВред рдХреНрдпрд╛ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ?
рдЖрдк vuetype
рдХрд╛ рдЙрддреНрдкрд╛рджрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП YouComponent.vue.d.ts
рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЬреЛ рдЖрдкрдХреЗ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЛ рдорд╛рдЙрдВрдЯ рдХрд┐рдП рдЧрдП рдШрдЯрдХ рдХреЗ рд╕рдЯреАрдХ рдкреНрд░рдХрд╛рд░ рдХреЛ рдмрддрд╛рдПрдЧрд╛ред
рдЖрдк рдкреНрд░рдЧрддрд┐ рдХреЗ рд▓рд┐рдП рдЗрд╕ рдореБрджреНрджреЗ рдХреЛ рднреА рдЯреНрд░реИрдХ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рд▓реЗрдХрд┐рди, рдореБрдЭреЗ рдпрд╣ рд╡рд┐рдЪрд╛рд░ рдкрд╕рдВрдж рдирд╣реАрдВ рд╣реИред рдпреЗ рдкрд░реАрдХреНрд╖рдг рд╣реИрдВ, рд╡реЗ рд╡рд┐рдлрд▓ рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВред рдХреЛрдИ рдмрдбрд╝реА рдмрд╛рдд рдирд╣реАрдВред
рдпрд╣реА рдХрд╛рд░рдг рд╣реИ рдХрд┐ рдореИрдВ (wrapper.vm as any).whatever
рд▓рд┐рдП рдЪрд┐рдкрдХреЗ рд░рд╣рддреЗ рд╣реИрдВред (wrapper.vm as any).whatever
рджреГрд╖реНрдЯрд┐рдХреЛрдг рд╣реИред рдпрд╣ рдореБрдЭреЗ рдкрд░реАрдХреНрд╖рдг рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╛рдлреА рд╕рдордп рдмрдЪрд╛рддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдбреЗрд╡рд▓рдкрд░ рдХрд╛ рдЕрдиреБрднрд╡ рдереЛрдбрд╝рд╛ рдЦрд░рд╛рдм рд╣реЛрддрд╛ рд╣реИред
рдЕрдкрдирд╛ рдирд┐рд░реНрдгрдп рдпрд╣рд╛рдБ рд▓реЗрдВ:
- рд╕рднреА рддрд░рд╣ рд╕реЗ
vuetype
рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ - рдЖрдВрд╢рд┐рдХ рд░реВрдк рд╕реЗ рдЗрд╕реЗ рд╕рдмрд╕реЗ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдШрдЯрдХреЛрдВ рдХреЗ рд▓рд┐рдП рд╕рдмрд╕реЗ рдмрдбрд╝реА рдорд╛рддреНрд░рд╛ рдореЗрдВ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЗ рд╕рд╛рде рд▓рд╛рдЧреВ рдХрд░реЗрдВ рдФрд░ рдЗрд╕реЗ рдирд┐рдпрдорд┐рдд рд░реВрдк рд╕реЗ рдЕрдкрдбреЗрдЯ рдХрд░реЗрдВ
any
рдПрдХ рд╡рд╛рдкрд╕реА рдХреЗ рд░реВрдк рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ
рдирд┐рд╖реНрдХрд░реНрд╖
рдкрд┐рдЫрд▓реЗ рдХреБрдЫ рд╡рд░реНрд╖реЛрдВ рдореЗрдВ Vue
рдкрд╛рд░рд┐рд╕реНрдерд┐рддрд┐рдХ рддрдВрддреНрд░ рдореЗрдВ typescript
рд╕рдорд░реНрдерди рдХрд╛ рдФрд╕рдд рд╕реНрддрд░ рдмрдврд╝рд╛:
Nuxt
рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ nuxt-ts
рдкреЗрд╢ рдХрд┐рдпрд╛ рдФрд░ рдЕрдм рдЬрд╣рд╛рдЬ ts
рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ рдмрдирд╛рддрд╛ рд╣реИVue@3
typescript
рд╕рдорд░реНрдерди рдореЗрдВ рд╕реБрдзрд╛рд░ рд╣реЛрдЧрд╛- рдЕрдзрд┐рдХ 3-рдкрдХреНрд╖ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдФрд░ рдкреНрд▓рдЧрдЗрдиреНрд╕ рдкреНрд░рдХрд╛рд░ рдХреА рдкрд░рд┐рднрд╛рд╖рд╛рдПрдВ рдкреНрд░рджрд╛рди рдХрд░реЗрдВрдЧреЗ
рд▓реЗрдХрд┐рди, рдлрд┐рд▓рд╣рд╛рд▓ рдпрд╣ рддреИрдпрд╛рд░ рд╣реИред рдпреЗ рд╕рд┐рд░реНрдл рд╕реБрдзрд╛рд░рдиреЗ рдХреА рдмрд╛рддреЗрдВ рд╣реИрдВ! рдЯрд╛рдЗрдк-рд╕реЗрдл Vue
рдХреЛрдб рд▓рд┐рдЦрдирд╛ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЖрдкрдХреЗ рдбреЗрд╡рд▓рдкрд░ рдПрдХреНрд╕рдкреАрд░рд┐рдпрдВрд╕ рдХреЛ рдмреЗрд╣рддрд░ рдмрдирд╛рддрд╛ рд╣реИ рдФрд░ рдЖрдкрдХреЛ рдХрдВрдкрд╛рдЗрд▓рд░ рдХреЛ рд╣реИрд╡реА-рд▓рд┐рдлреНрдЯрд┐рдВрдЧ рдЫреЛрдбрд╝рдиреЗ рдХреЗ рджреМрд░рд╛рди рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╕рд╛рдорд╛рди рдкрд░ рдзреНрдпрд╛рди рдХреЗрдВрджреНрд░рд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред
Vue
рдРрдкреНрд╕ рдЯрд╛рдЗрдк рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдкрдХреЗ рдкрд╕рдВрджреАрджрд╛ рд╣реИрдХ рдФрд░ рдЯреВрд▓ рдХреНрдпрд╛ рд╣реИрдВ? рдЖрдЗрдП рдЯрд┐рдкреНрдкрдгреА рдЕрдиреБрднрд╛рдЧ рдореЗрдВ рдЗрд╕рдХреА рдЪрд░реНрдЪрд╛ рдХрд░реЗрдВред