Если вы спросите двух разработчиков Vue.js: «Как лучше всего использовать AJAX в приложении?» вы получите три разных мнения.
Vue не предоставляет официального способа реализации AJAX, и существует ряд различных шаблонов проектирования, которые можно эффективно использовать. Каждый имеет свои плюсы и минусы и должен оцениваться в соответствии с требованиями. Вы даже можете использовать несколько одновременно!
В этой статье я покажу вам четыре места, где вы можете реализовать AJAX в приложении Vue:
- Корневой экземпляр.
- Компоненты .
- Vuex действия.
- Маршрут навигационной охраны.
Я объясню каждый подход, приведу пример и расскажу о плюсах и минусах.
1. Корневой экземпляр
С помощью этой архитектуры вы отправляете все ваши запросы AJAX из корневого экземпляра и сохраняете там все состояния. Если какие-либо подкомпоненты нуждаются в данных, они будут считаться реквизитом. Если субкомпонентам нужны обновленные данные, для запроса корневого экземпляра будет использоваться пользовательское событие.
Пример:
JavaScript
1
new Vue({
2
data: {
3
message: ''
4
},
5
methods: {
6
refreshMessage(resource) {
7
this.$http.get('/message').then((response) {
8
this.message = response.data.message;
9
});
10
}
11
}
12
})
13
Vue.component('sub-component', {
15
template: '<div>{{ message }}</div>',
16
props: [ 'message' ]
17
methods: {
18
refreshMessage() {
19
this.$emit('refreshMessage');
20
}
21
}
22
});
Pros
- Хранит всю вашу логику и данные AJAX в одном месте.
- Делает ваши компоненты "тупыми", чтобы они могли сосредоточиться на презентации.
Cons
- По мере расширения вашего приложения требуется много реквизита и пользовательских событий.
Вы можете также , как:
Создание приложения реального времени данных с помощью Vue.js .
2. Компоненты
Благодаря этой архитектуре компоненты отвечают за управление своими собственными AJAX-запросами и независимое состояние. На практике вы, вероятно, захотите создать несколько «контейнерных» компонентов, которые управляют данными для их собственной локальной группы «презентационных» компонентов.
Например, filter-list
может быть упаковка компонента контейнера filter-input
и filter-reset
, которые служат компонентами представления. filter-list
будет содержать логику AJAX и будет управлять данными для всех компонентов в этой группе, связываясь через реквизиты и события.
Посмотрите Презентационные и Контейнерные Компоненты Дана Абрамова для лучшего описания этого образца.
Чтобы упростить реализацию этой архитектуры, вы можете абстрагировать любую логику AJAX в a mixin
, а затем использовать mixin
компонент in для включения AJAX.
JavaScript
xxxxxxxxxx
1
let mixin = {
2
methods: {
3
callAJAX(resource) {
4
5
}
6
}
7
}
8
Vue.component('container-comp', {
10
// No meaningful template, I just manage data for my children
11
template: '<div><presentation-comp :mydata="mydata"></presentation-comp></div>',
12
mixins: [ myMixin ],
13
data() {
14
return { }
15
},
16
})
18
Vue.component('presentation-comp', {
20
template: <div>I just show stuff like {{ mydata }}</div>,
21
props: [ 'mydata' ]
22
})
Pros
- Сохраняет компоненты отделенными и многоразовыми.
- Получает данные, когда и где это необходимо.
Cons
- Нелегко обмениваться данными с другими компонентами или группами компонентов.
- Компоненты могут иметь слишком много обязанностей и дублировать функциональность.
3. Vuex Actions
С помощью этой архитектуры вы управляете как состоянием, так и логикой AJAX в своем магазине Vuex. Компоненты могут запрашивать новые данные, отправляя действие.
Если вы реализуете этот шаблон, хорошей идеей будет вернуть обещание из вашего действия, чтобы вы могли реагировать на разрешение запроса AJAX, например, скрыть спиннер загрузки, повторно включить кнопку и т. Д.
JavaScript
xxxxxxxxxx
1
store = new Vuex.Store({
2
state: {
3
message: ''
4
},
5
mutations: {
6
updateMessage(state, payload) {
7
state.message = payload
8
}
9
},
10
actions: {
11
refreshMessage(context) {
12
return new Promise((resolve) => {
13
this.$http.get('...').then((response) => {
14
context.commit('updateMessage', response.data.message);
15
resolve();
16
});
17
});
18
}
19
}
20
});
21
Vue.component('my-component', {
23
template: '<div>{{ message }}</div>',
24
methods: {
25
refreshMessage() {
26
this.$store.dispatch('refeshMessage').then(() => {
27
// do stuff
28
});
29
}
30
},
31
computed: {
32
message: { return this.$store.state.message; }
33
}
34
});
Мне нравится эта архитектура, потому что она прекрасно разделяет ваше состояние и логику представления. Если вы используете Vuex, это путь. Если вы не используете Vuex, это может быть достаточно веской причиной.
Pros
- Все плюсы архитектуры корневых компонентов, без необходимости реквизита и пользовательских событий.
Cons
- Добавляет накладные расходы Vuex.
4. Маршрут навигационной охраны
Благодаря этой архитектуре ваше приложение разбивается на страницы, и все данные, необходимые для страницы и ее подкомпонентов, выбираются при изменении маршрута.
Основным преимуществом этого подхода является то, что он действительно упрощает ваш пользовательский интерфейс. Если компоненты независимо получают свои собственные данные, страница будет непредсказуемым образом перерисовываться, поскольку данные компонента заполняются в произвольном порядке.
Удобный способ реализовать это - создать конечные точки на вашем сервере для каждой страницы, например /about
, и /contact
т. Д., Которые соответствуют именам маршрутов в вашем приложении. Затем вы можете реализовать универсальный beforeRouteEnter
хук, который объединит все свойства данных с данными компонента страницы:
JavaScript
xxxxxxxxxx
1
import axios from 'axios';
2
router.beforeRouteEnter((to, from, next) => {
4
axios.get(`/api${to.path}`).then(({ data }) => {
5
next(vm => Object.assign(vm.$data, data))
6
});
7
})
Pros
- Делает интерфейс более предсказуемым.
Cons
- В целом медленнее, поскольку страница не может отображаться, пока все данные не будут готовы.
- Не очень поможет, если вы не используете маршруты.
Образец бонуса: сервер-рендеринг первого вызова AJAX на страницу
Не рекомендуется использовать AJAX для получения состояния приложения при начальной загрузке страницы, так как для этого требуется дополнительная передача данных на сервер, что задержит рендеринг вашего приложения.
Вместо этого вставьте начальное состояние приложения во встроенный скрипт в заголовке HTML-страницы, чтобы оно было доступно приложению в качестве глобальной переменной, как только это необходимо.
HTML
xxxxxxxxxx
1
<html>
2
...
3
<head>
4
...
5
<script type="text/javascript">
6
window.__INITIAL_STATE__ = '{ "data": [ ... ] }';
7
</script>
8
</head>
9
<body>
10
<div id="app"></div>
11
</body>
12
</html>
Затем AJAX можно использовать более подходящим образом для последующих выборок данных.
Если вы хотите узнать больше об этой архитектуре, ознакомьтесь с моей статьей « Избегайте использования этого распространенного анти-паттерна в приложениях Full-Stack Vue / Laravel» .
Спасибо React AJAX Best Practices от Эндрю Х. Фармера за вдохновение.