Vue.js / Firebase и Vuefire - чтение и обновление одного объекта
Я пытался настроить простое приложение для тестирования некоторых функций Vue.js, и я нашел здесь и там несколько интересных руководств по базовой реализации CRUD.
Несколько дней я застрял на чем-то немного другом, вот простое описание того, чего я пытаюсь достичь:
- Настройте домашнюю страницу, которая отображает имя и фамилию.
- Сохраните имя и фамилию в базе данных как строки
- Просто отобразите две строки на экране
- Позже разрешите вошедшему в систему пользователю редактировать строку (здесь это не является частью моей проблемы, но важно объяснить, почему мне нужно хранить два поля в Firebase)
Я уже работал над небольшой архитектурой с управлением входом в систему, различными меню для состояний входа / выхода, и тому подобное.
Так что я уже настроил это в конфигурации Firebase: Firebase
Тогда вот мои основные файлы:
main.js
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'
import firebase from 'firebase'
import VueFire from 'vuefire'
import { store } from './store/store'
let app
let config = {
apiKey: '######',
authDomain: '######',
databaseURL: '######',
projectId: '######',
storageBucket: '######',
messaginSenderId: '######'
}
firebase.initializeApp(config)
firebase.auth().onAuthStateChanged(function (user) {
if (!app) {
/* eslint-disable no-new */
app = new Vue({
el: '#app',
store: store,
router,
template: '<App/>',
components: { App }
})
}
})
export const db = firebase.database()
export const homeContent = db.ref('homeContent')
Vue.config.productionTip = false
index.js
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
import Test from '@/components/Test'
import Login from '@/components/Login'
import SignUp from '@/components/SignUp'
import firebase from 'firebase'
import VueFire from 'vuefire'
Vue.use(Router)
Vue.use(VueFire)
let router = new Router({
routes: [
{
path: '*',
redirect: '/login'
},
{
path: '/',
redirect: '/login'
},
{
path: '/login',
name: 'Login',
component: Login
},
{
path: '/test',
name: 'Test',
component: Test,
meta: {
requiresAuth: true
}
},
{
path: '/sign-up',
name: 'SignUp',
component: SignUp
},
{
path: '/hello-world',
name: 'HelloWorld',
component: HelloWorld,
meta: {
requiresAuth: true
}
}
]
})
router.beforeEach((to, from, next) => {
let currentUser = firebase.auth().currentUser
let requiresAuth = to.matched.some(record => record.meta.requiresAuth)
if (requiresAuth && !currentUser) next('/login')
else if (!requiresAuth && currentUser) next()
else next()
})
export default router
App.vue
<template>
<div id="app">
<div v-if="user">Logged in</div>
<div v-else>NOT logged in</div>
<Navigation></Navigation>
<button id="btLogout" v-if="user" v-on:click="logout">Déconnexion</button>
<img class="logo" src="./assets/logo.png">
<router-view/>
</div>
</template>
<script>
// Register Navbar component
import Navigation from './components/Nav.vue'
import firebase from 'firebase'
export default {
computed: {
user () {
return this.$store.getters.getUser
}
},
components: {
'Navigation': Navigation
},
methods: {
logout: function () {
firebase.auth().signOut().then(() => {
this.$store.dispatch('clearUser')
this.$router.replace('login')
})
},
setUser: function () {
this.$store.dispatch('setUser')
}
},
created () {
// when the app is created run the set user method
// this uses Vuex to check if a user is signed in
// check out mutations in the store.js file
this.setUser()
}
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
.logo {
width: 50px;
height: auto;
clear: both;
display: block;
margin: 30px auto 0;
}
#btLogout {
clear: both;
display: inline-block;
}
</style>
Test.vue
<template>
<div class="homeScreen">
<p v-bind:key="homeContent['.key']" v-for="firstName of homeContent">{{ homeContent.firstName }}</p>
<p v-bind:key="homeContent['.key']" v-for="lastName of homeContent">{{ homeContent.lastName }}</p>
<img src="../assets/annonce_motw.jpg">
</div>
</template>
<!-- Javascript -->
<script>
import firebase from 'firebase'
import db from "../main"
export default {
data () {
return {
db: ''
}
},
firebase: {
homeContent: {
source: db.ref('homeContent'),
asObject: true
}
},
methods: {
setHomeName (key) {
// homeName.child(key).update({ edit: true })
}
},
created () {
}
}
</script>
<!-- SASS styling -->
<style scoped>
</style>
И вот я здесь. Часть, в которой я застрял, заключается в том, что каждый раз, когда я пытаюсь добавить в Test.vue строку db.ref('homeContent'), консоль возвращает, что db не определена.
Я также не могу понять, как просто вывести сохраненные строки после решения проблемы с консолью.
Так что я сделал не так?:D
Спасибо и заранее за каждую помощь, которую вы принесете! Ура!
1 ответ
Линия
export const db = firebase.database()
исполняется раньше firebase.initializeApp(config)
завершил выполнение, поэтому он будет неопределенным.
Один из способов решить эту проблему - поместить инициализированный объект Firebase в прототип Vue:
Vue.prototype.$firebase = Firebase.initializeApp(config)
Затем внутри любого из ваших компонентов, таких как Test.vue, вы можете ссылаться на объект Firebase следующим образом:
firebase: {
homeContent: {
source: this.$firebase.database().ref('homeContent'),
asObject: true
}
},
Одно предостережение: это работает, только если вы создаете приложение Vue после того, как знаете, что Firebase завершил инициализацию. Вы сделали это правильно, поставив new Vue()
заявление внутри firebase.auth().onAuthStateChanged()
в main.js, так что вам гарантированно будет доступен инициализированный объект Firebase по адресу this.$firebase
в любом из ваших компонентов.