Vue.js / Firebase和Vuefire - 读取和更新单个对象

时间:2018-02-15 22:48:56

标签: firebase firebase-realtime-database vue.js vuefire

我一直在尝试设置一个简单的应用来测试一些Vue.js功能,我一直在这里找到一些关于基本CRUD实现的有趣教程。

我几天后就被困在了一些不同的东西上,这里有一个我想要实现的简单描述:

  • 设置显示姓名的主页。
  • 在firebase中将名字和姓氏存储为字符串
  • 只需在屏幕上显示两个字符串
  • 稍后允许登录用户编辑字符串(这不是我的问题的一部分,但相关解释为什么我需要将两个字段存储在Firebase中)

我已经开始使用登录管理的小型架构,登录/退出状态的不同菜单,等等。

所以我已经在Firebase中设置了它: Firebase configuration

然后是我的核心文件:

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(&#39; homeContent&#39;)控制台返回db未定义。

我也无法解决在解决控制台问题后如何简单输出存储的字符串。

那我做错了什么? :D

感谢并提前为您带来的每一件帮助!干杯!

1 个答案:

答案 0 :(得分:0)

该行

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
  }
},

一个警告:这只有在您知道Firebase完成初始化后创建Vue应用程序时才有效。您通过将new Vue()语句放在main.js中的firebase.auth().onAuthStateChanged()内来正确执行此操作,因此您可以确保在this.$firebase的任何组件中都可以使用已初始化的Firebase对象。