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 в любом из ваших компонентов.

Другие вопросы по тегам