#vue.js #vuejs2 #vue-component #vuex
#vue.js #vuejs2 #vue-компонент #vuex
Вопрос:
Когда я отправляю действие в компоненте App.vue в перехвате жизненного цикла mounted (), оно запускается после загрузки других компонентов. Я использую async / await в своем действии и подключил крючок жизненного цикла.
Файл App.vue
methods: {
...mapActions({
setUsers: "setUsers",
}),
},
async mounted() {
try {
await this.setUsers();
} catch (error) {
if (error) {
console.log(error);
}
}
},
action.js файл:
async setUsers(context) {
try {
const response = await axios.get('/get-users');
console.log('setting users');
if (response.data.success) {
context.commit('setUsers', {
data: response.data.data,
});
}
} catch (error) {
if (error) {
throw error;
}
}
},
В компоненте списка пользователей мне нужно получить пользователей из vuex. Итак, я использую mapGetters для получения списка пользователей.
...mapGetters({
getUsers: "getUsers",
}),
mounted() {
console.log(this.getUsers);
},
Но проблема заключается в том, что «настройка входа пользователей» в консоль выполняется после входа в консоль this.getUsers
. .
В компоненте списка пользователей я могу использовать getUsers в шаблоне, но когда я пытаюсь войти в консоль.getUsers, это ничего не дает.
Как я могу запустить app.vue
file перед запуском любых других компонентов?
Ответ №1:
Вы правильно используете async await в своих компонентах. Важно понимать, что async await
это не задерживает выполнение вашего компонента, и ваш компонент все равно будет отображаться и проходить через различные перехваты жизненного цикла, такие как mounted
.
Что async await
делает, так это задерживает выполнение текущего контекста, если вы используете его внутри функции, код после await
того, как обещание будет выполнено, и в вашем случае вы используете его в created
перехвате жизненного цикла, что означает, что код внутри mounted
перехвата жизненного цикла, который является функцией, будетрешается после ожидания.
Итак, что вы хотите сделать, это убедиться, что вы визуализируете компонент только при получении данных.
Вот как это сделать:
- Если компонент является дочерним компонентом родительского компонента, который вы можете использовать
v-if
, то при поступлении данных установите для data значение true, например:
data() {
return {
hasData: false,
}
}
async mounted() {
const users = await fetchUsers()
this.hasData = true;
}
<SomeComponent v-if="hasData" />
- Если компонент не является дочерним по отношению к родительскому, вы можете использовать a
watcher
, чтобы сообщить вам, когда компонент отрисовал. При использованииwatch
вы можете быть осторожны, потому что это будет происходить каждый раз, когда происходит изменение.
Простое эмпирическое правило заключается в использовании watch с переменными, которые меняются не часто, если данные, которые вы получаете, в основном доступны только для чтения, вы можете использовать данные, если нет, вы можете добавить свойство в Vuex, например loadingUsers
.
Вот пример того, как это сделать:
data: {
return {
hasData: false,
}
},
computed: {
isLoading() {
return this.$store.state.app.users;
}
},
watch: {
isLoading(isLoading) {
if (!isLoading) {
this.hasData = true;
}
}
}
<SomeComponent v-if="hasData" />
Ответ №2:
если вы извлекаете данные из API, то лучше отправить действие внутри created, где DOM еще не визуализирован, но вы все равно можете использовать «this» вместо mounted . Вот пример, если вы работаете с модулями Vuex:
created() {
this.fetchUsers();
},
methods: {
async fetchUsers() {
await this.$store.dispatch('user/setUsers');
},
},
computed: {
usersGetters() {
// getters here
},
},
Ответ №3:
Вопрос: Вы ожидаете await this.setUsers();
, что приложение будет запускаться каждый раз при загрузке (независимо от того, какая страница / компонент отображается)?
Если да, то у вас App.vue
все в порядке. И в вашем «компоненте списка пользователей» его также можно использовать mapGetters
для получения значений (обратите внимание, что оно должно быть вычислено). Проблема в том, что сначала вы должны «дождаться» завершения setUsers
действия, чтобы ваш getUsers
компонент мог иметь значение.
Простой способ исправить это — использовать условный рендеринг и отображать компонент только тогда, когда getUsers
он определен. Возможно, вы можете добавить a v-if
в свой родительский компонент «Компонента списка пользователей» и загружать его только тогда, когда v-if="getUsers"
значение true. Тогда ваша смонтированная логика также будет работать нормально (поскольку данные уже есть).