Как известно Vue базируется на паттерне MVVM, собрате MVC. Данная конструкция подразумевает обработку данных на сервере(back) и отображении результатов на front-е, т.е. приложении на vue. Но, по мере развития, задачи back сдвигаются и он уже не занимается глубокой обработкой данных, а всё чаще выдаёт "сырые" данные как есть, выполняет роль API. И тут возникает проблема, поскольку места в теге <script /> компонента недостаточно для обработки сколь нибудь значимых объёмов данных. Код становится перегруженным и тяжело читаемым.
Vuex
В помощь для обработке данных предлагается vuex. Но его концепция давно устарела. Она подразумевает имитацию реактивности, через вызовы мутаций. Те, кто с ним сталкивается впервые понимают всю убогость его использования, когда простая операция присваивания заменяется танцами с мутациями и actions. И это ещё тыкнем пальцем умолчим про реактивность в структурах данных и использование с v-model. А когда слышишь про необходимость выдумывать константы для обозначения названий actions, то становится совсем грустно.
Впрочем, если вы считаете vuex единственно верным решением, можете закрыть эту статью.
Model, что может быть проще?
А что если заимствовать model из распространённого MVC? Берём и всю обработку данных поручаем отдельной модели, в т.ч. и общение с API, а в самом компоненте только подключение необходимых моделей.
При этом модель может содержать как списки, так и сложные структуры, хотя если структуры сложные, то их лучше разбить на более мелкие модели.
Рассмотрим простую задачу. Пусть нам необходимо создать форму, в которой будет поле id, а так же поля с именем и фамилией пользователя. После ввода id, в форму должны подгружаться данные о соответствующем пользователе.

Создадим модель пользователя, (файл UserModel.js):
import Model from "Model";
class User extends Model {
id = 0 // Number
name = '' // String
family = '' // String
}
export default User
Модель формы (файл FormModel.js):
import Model from "Model";
import User from "./User";
import api from 'api'
class Form extends Model {
user = new User()
get id(){
return this.user.id
}
set id(id){
api(id).then(
(user) => {
this._loadData({ user: user })
}).catch(() => {
this.user = new User()
})
}
}
export default new Form()
api.js
const users = [{
id: 1,
name: 'Вася',
family: 'Иванов'
},{
id: 2,
name: 'Петя',
family: 'Петров'
}]
// Эмулируем загрузку с сервера
export default function (id){
return new Promise((resolve, reject) => {
setTimeout(() => {
const user =users.find((user) => (user.id == id))
if(user) {
resolve(user)
}else {
reject(new Error('user not found'))
}
}, 2000)
})
}
Ну и сам компонент Form.vue
<template>
<form>
<div>
<label>id: <input v-model="Form.id" /></label>
</div>
<div>
<label>Имя: <input v-model="Form.user.name"/></label>
</div>
<div>
<label>Фамилия: <input v-model="Form.user.family"/></label>
</div>
</form>
</template>
<script>
import Form from "../Model/Form";
export default {
name: "Form",
data(){
return {
Form
}
}
}
</script>
Для того, чтобы все свойства и методы модели стали реактивными, достаточно поступить так:
import Form from "../Model/Form";
export default {
data(){
return {
Form
}
}
}
Можно этот же экземпляр модели можно использовать и в другом компоненте:
<template>
<div id="app">
<Form></Form>
<pre>{{ userJSON }}</pre>
</div>
</template>
<script>
import Form from "./components/Form";
import FormModel from './Model/Form'
export default {
name: 'App',
components: {
Form
},
data(){
return {
FormModel
}
},
computed:{
userJSON(){
return JSON.stringify( this.FormModel.user, null, " ")
}
}
}
</script>
для этого в модуле модели формы нужно экспортировать сам экземпляр объекта формы:
class Form extends Model {
...
}
export default new Form()
Базовый класс модели с загрузчиком и проверкой типов загружен на гитхаб в виде библиотеки. Файлы с примерами расположены в самой библиотеке.