# #javascript #firebase #vue.js #firebase-authentication
Вопрос:
В настоящее время я работаю над простым Vue.js приложение, в котором пользователь может зарегистрироваться и войти в систему. Для входа в систему и регистрации я работаю с аутентификацией Firebase. До сих пор мне удавалось заставить пользователя успешно войти в систему и изменить состояние навигационной панели: когда пользователь выходит из системы, на ней отображаются 2 кнопки: одна кнопка входа, а другая-кнопка регистрации. Когда пользователь входит в систему, эти кнопки заменяются именем пользователя и возможностью выхода. Проблема связана с опцией регистрации: сразу после заполнения формы и нажатия кнопки «Отправить» состояние навигационной панели изменяется, появляется опция «Выйти», но имя пользователя не отображается. Я хочу либо отобразить имя пользователя, а также кнопку выхода, либо чтобы приложение не входило в систему сразу после регистрации пользователя. Есть ли способ сделать это?
Скрипт формы регистрации:
import firebase from "firebase";
export default {
name: 'Sign-Up',
components: {
},
data() {
return {
form: {
errors: [],
name: "",
email: "",
username: "",
password: ""
},
error: null
};
},
methods: {
submit() {
firebase
.auth()
.createUserWithEmailAndPassword(this.form.email, this.form.password)
.then(data => {
data.user
.updateProfile({
displayName: this.form.name
})
.then(() => {})
.then(this.$router.replace({ name: "Profile" }))
})
.catch(err => {
this.error = err.message;
});
}
}
}
Навигационная панель
<template v-if="user.loggedIn">
<ul class="nav col-12 col-md-auto mb-2 justify-content-center mb-md-0">
<li style="margin-top: 0.5em;"><router-link to="/Dashboard" class="nav-link px-2">Hello, {{user.data.displayName}}</router-link></li>
<li><a href="#" class="nav-link px-2" @click.prevent="signOut"><button type="button" class="btn poke-secondary me-2">Sign out</button></a></li>
</ul>
</template>
<template v-else>
<div class="col-md-3 text-end px-2">
<router-link to="/login"><button type="button" class="btn poke-secondary me-2">Login</button></router-link>
<router-link to="/signup"><button type="button" class="btn poke-secondary">Sign Up</button></router-link>
</div>
</template>
<script>
import { mapGetters } from "vuex";
import firebase from "firebase/app";
export default {
name: "Header",
computed: {
...mapGetters({
user: "user"
})
},
methods: {
signOut() {
firebase
.auth()
.signOut()
.then(() => {
this.$router.replace({
name: "Home"
});
});
}
}
};
</script>
store.js:
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({
state: {
user: {
loggedIn: false,
data: null
}
},
getters: {
user(state){
return state.user
}
},
mutations: {
SET_LOGGED_IN(state, value) {
state.user.loggedIn = value;
},
SET_USER(state, data) {
state.user.data = data;
}
},
actions: {
fetchUser({ commit }, user) {
commit("SET_LOGGED_IN", user !== null);
if (user) {
commit("SET_USER", {
displayName: user.displayName,
email: user.email
});
} else {
commit("SET_USER", null);
}
}
}
});
Комментарии:
1. Вероятно, вы захотите вернуть обещание, которое будет выполнено, когда пользовательские данные будут полностью доступны. Ответ Firebase является асинхронным, поэтому он может быть недоступен не сразу.
Ответ №1:
Я хочу либо отобразить имя пользователя, а также кнопку выхода, либо чтобы приложение не входило в систему сразу после регистрации пользователя. Есть ли способ сделать это?
Как объясняется в документе, с createUserWithEmailAndPassword()
помощью метода «при успешном создании учетной записи пользователя этот пользователь также войдет в ваше приложение».
Таким образом, невозможно избежать входа пользователя в систему «сразу после регистрации пользователя». Ваша проблема заключается в том updateProfile()
, что метод асинхронен: перед обновлением возникает небольшая задержка displayName
. Вы должны справиться с этим случаем, например, отображая Hello, {{user.data.displayName}}
строку и кнопку «Выйти» только в том случае, если displayName
она не равна нулю.
Ответ №2:
Как объяснил @Renaud, пользователь войдет в систему сразу после createUserWithEmailAndPassword
разрешения метода, отображая этот div только тогда, когда displayName
он не равен нулю, что может быть сделано v-if="user.data.displayName !== null"
.
Альтернативой было бы использовать облачную функцию для создания новых пользователей, если вы действительно не хотите такой задержки при отображении имени пользователя. Поскольку пользователи создаются с помощью пакета SDK администратора в облачной функции, они не будут входить в систему на клиенте. Простая вызываемая функция для того же будет:
exports.createNewUser = functions.https.onCall((data, context) => {
const {email, password, displayName} = data
return admin.auth().createUser({ email, password, displayName }).then((userRecord) => {
console.log('Successfully created new user:', userRecord.uid);
return {data: userRecord.uid}
})
});
Эта функция создаст нового пользователя с предоставленными учетными данными и именем пользователя. Вы можете вызвать эту функцию из своего приложения Vue следующим образом:
methods: {
submit() {
const createUser = firebase.functions().httpsCallable('createNewUser');
createNewUser({
email: this.form.email,
password: this.form.password,
displayName: this.form.name
}).then((result) => {
const result = result.data;
// Manually sign in user now
// signInWithEmailAndPassword(this.form.email, this.form.password)
});
}
}