Vue.js makes it incredibly easy to create dynamic web interfaces. Firebase makes it incredibly easy to create a persistent, realtime backend. Combining the two would give us possibly the easiest way to build a data-driven web application. Now with VueFire, an unofficial Firebase binding library for Vue.js, it only takes a few lines of code to reactively render your Firebase data in your app.

What is Vue.js?

Vue.js is a JavaScript framework for building dynamic web interfaces. It offers reactive data binding and composable components in an extremely approachable core library, which can be dropped into any existing page and picked up in a matter of hours. On the other hand, the framework also provides more opinionated solutions for more ambitious use cases, such as client-side routing, state management and advanced build tools. It currently has over 15,000 stars on GitHub and is rapidly rising in popularity. You can visit vuejs.org for a more thorough introduction.

Adding Firebase to a Vue.js app

It is already pretty simple to manually update a Vue instance's data when a Firebase reference's value has changed, but the VueFire library makes it even easier.

Setting up the scripts

To get started, just include Vue, Firebase and VueFire in your page:

<head>
  <!-- Vue -->
  <script src="https://cdn.jsdelivr.net/vue/latest/vue.js"></script>
  <!-- Firebase -->
  <script src="https://cdn.firebase.com/js/client/2.4.2/firebase.js"></script>
  <!-- VueFire -->
  <script src="https://cdn.jsdelivr.net/vuefire/1.0.0/vuefire.min.js"></script>
</head>

VueFire will automatically detect Vue's presence and install itself. If you are using a module bundler, you can also install the dependencies via NPM:

npm install vue firebase vuefire --save
var Vue = require("vue");
var VueFire = require("vuefire");
var Firebase = require("firebase");

// explicit installation is required in a module environment
Vue.use(VueFire);

Binding Vue.js templates to Firebase data

With proper installation, your Vue components can now accept a new option: firebase. You can use this option to declaratively bind Firebase references to properties on your Vue instance:

var itemsRef = new Firebase("https://vuefiredemo.firebaseio.com/items/");

var vm = new Vue({
  el: "#app",
  firebase: {
    // can bind to either a direct Firebase reference or a query
    items: itemsRef.limitToLast(25)
  }
});

And the HTML:

<body>
  <div id="app">
    <ul>
      <li v-for="item in items">
        {{ item.text }}
        <button @click="removeTodo(item['.key'])">X</button>
      </li>
    </ul>
    <form @submit.prevent="addTodo">
      <input v-model="newTodo" />
      <button>Add #{{ items.length }}</button>
    </form>
  </div>
</body>

Now whenever the Firebase reference's value changes, the DOM will be updated accordingly. Isn't that easy?

Updating Firebase data on user interaction

Now all we need to do is allow the user to update the list of items. First let's create a form that enables adding items:

<body>
  <div id="app">
    <form v-on:submit.prevent="addTodo">
      <input v-model="newTodo">
      <button>Add #{{ items.length }}</button>
    </form>

   </div>
</body>

The <input> element is bound to a variable named newTodo, so we need to declare that in the component's data option. We use the v-on directive to listen to form submission. The .prevent is a modifier that tells Vue.js to automatically call preventDefault() on the event to prevent page reload. We also need to define the addTodo() method which will be called when the form is submitted:


var vm = new Vue({
  el: "#app",
  firebase: {
    items: itemsRef.limitToLast(25)
  },
  // declare local state
  data: {
    newTodo: ""
  },
  // define instance methods
  methods: {
    addTodo: function () {
      if (this.newTodo.trim()) {
        // update the Firebase reference!
        itemsRef.push({
          text: this.newTodo
        });
        // reset input box
        this.newTodo = "";
      }
    }
  }
});

Finally, we can add a button for each item that enables removal and this is the final code for our little demo. Note the @ bindings are shorthand for v-on:

Setting bindings in the HTML

<body>
  <div id="app">
    <ul>
      <li v-for="item in items">
        {{ item.text }}
        <button @click="removeTodo(item['.key'])">X</button>
      </li>
    </ul>
    <form @submit.prevent="addTodo">
      <input v-model="newTodo">
      <button>Add #{{ items.length }}</button>
    </form>

   </div>
</body>

Creating the model in JavaScript

var itemsRef = new Firebase("https://vuefiredemo.firebaseio.com/items/");

new Vue({
  el: "#app",
  data: {
    newTodo: ""
  },
  firebase: {
    items: itemsRef.limitToLast(25)
  },
  methods: {
    removeTodo: function (key) {
      itemsRef.child(key).remove();
    },
    addTodo: function () {
      if (this.newTodo.trim()) {
        itemsRef.push({
          text: this.newTodo
        });
        this.newTodo = "";
      }
    }
  }
});

You can find the source code for this demo and more detailed docs at the VueFire GitHub repo.

Conclusion

With around 30 lines of code, we now have a dynamic interface entirely driven by a remote data source, with updates propagated to multiple clients in realtime. The Vue.js + Firebase combination makes building these types of apps faster and easier than ever before.

The Vue.js team is also investigating Firebase integration with Vuex, Vue.js' official client-side state management solution. This would provide a scalable pattern for managing Firebase data in large scale single-page applications.

We believe Vue.js and Firebase are a perfect match for building modern web apps, and we are excited to see what you create!