javascript #vue.js #inertiajs #jetstream
#javascript #vue.js #inertiajs #jetstream
Вопрос:
Фон
У нас есть страница оформления заказа, которая перенаправляется на Stripe после создания объекта order. Поскольку это происходит через запрос API, это занимает немного времени. Поэтому нам нужно заблокировать кнопку «Оформить заказ» после ее нажатия, чтобы ее нельзя было нажимать несколько раз.
В настоящее время мы делаем это, показывая значок загрузки при нажатии кнопки, для достижения этого мы переключаем значение переменной.
Приложение находится в Laravel с Jetstream (без инерции), и мы ограничены в плане самостоятельного сброса значений при успешном завершении формы из-за инерции.
Проблема
Это работает нормально, если пользователь не нажмет кнопку возврата в браузере после перенаправления на Stripe. Если они это сделают, значок загрузки останется видимым, и, похоже, Vue не сбрасывает состояние переменной на false.
Пример кода
<template>
<div>
<div v-if="loadingCheckout">Loading</div>
<button v-if="!loadingCheckout" @click="startPurchase">Checkout</button>
</div>
</template>
<script>
import { defineComponent, ref } from 'vue'
export default defineComponent({
data() {
return {
loadingCheckout: false,
};
},
methods: {
startPurchase() {
this.loadingCheckout = true;
// Create checkout logic
}
}
})
</script>
Попытки решения
Мы пытались использовать сброс событий, таких как setUp
, beforeMount
, mounted
но безуспешно. Кроме того, я пытался использовать ref
внутреннюю настройку вместо подхода к данным, но возникает та же проблема.
Мы также пытались использовать метод для создания свойства data, но та же проблема. Также пытались использовать обратные вызовы по инерции в форме, например, onSuccess
однако они не срабатывают, предполагая, что это связано с вмешательством JetStream.
Любые идеи были бы полезны, идеальным является то, что мы можем применять это состояние только во время каждого рендеринга страницы и никогда не сохранять его в памяти. Я думаю, что проблема связана с сохранением состояния Inertia / Vue в истории браузера.
Комментарии:
1.
As this is via an API request it takes a little bit of time.
Есть ли обработчик завершения для этого запроса API? Выдает ли это ошибку, если транзакция не завершена?2. @jrend по завершении перенаправляет страницу на Stripe, в случае сбоя выдает ошибку, которую инерция затем обрабатывает для отображения. Я вижу, что обработчик завершения не работает, см. параграф 2 раздела «Попытки решения»
3. Поможет ли это, если вы поместите инициализацию свойства внутри смонтированного или созданного хука? При установке будет установлено это значение.loadingCheckout = false. Это должно вызвать его, даже если клиент нажимает назад.
4. @equi Я попробовал это, да, и ничего не произошло, хотя журнал консоли действительно появляется, поэтому я знаю, что он запущен. Я предполагаю, что в жизненном цикле установка значений с помощью Vue происходит после монтирования модуля
Ответ №1:
Вы можете попробовать с помощью onpopstate обновлять страницу всякий раз, когда вы нажимаете на кнопку «Назад».
window.onpopstate = function () {
// reset your state
};
Ответ №2:
Чтобы решить эту проблему, я перешел от использования методов инерционной формы https://inertiajs.com/forms#submitting-forms и вместо этого использовал вспомогательные методы формы https://inertiajs.com/forms#form-helper у которых есть работающие обратные вызовы.
Заменив
this.$inertia.post(route('purchase.store'));
с
this.$inertia.form().post(route('purchase.store'), {
onFinish: () => this.loadingCheckout = false,
})
Теперь мой код выглядит следующим образом:
<template>
<div>
<div v-if="loadingCheckout">Loading</div>
<button v-if="!loadingCheckout" @click="startPurchase">Checkout</button>
</div>
</template>
<script>
import { defineComponent, ref } from 'vue'
export default defineComponent({
data() {
return {
loadingCheckout: false,
};
},
methods: {
startPurchase() {
this.loadingCheckout = true;
// Create checkout logic
this.$inertia.form().post(route('purchase.store'), {
preserveScroll: true,
onFinish: () => this.loadingCheckout = false,
})
}
}
})
</script>