Plugin to help us work with PouchDB in a Vuejs application

This post assumes that you at least have some working knowledge of Vuejs and PouchDB.
Don’t worry i'm not going to tell you to install 1000 things before you get started. All you need is Vuejs and PouchDB.
Plugins provides a way for you to add global-level functionality to Vue. For example Vue by itself doesn’t have a built-in routing system. Vue-router plugin adds a routing functionality to Vue. There are very few resources on how to create a vuejs plugin, so i hope this will help.
Before diving into the details of building, have a look at how you will be able to use this plugin we are about to make.
var app = new Vue({ | |
el:"#app", | |
data: { | |
text:'' | |
}, | |
pouchdb:{ | |
todos: new PouchDB("todos") // this will be reactive | |
}, | |
methods: { | |
addTodo: function(){ | |
var todo = { | |
_id: new Date().toIsoString(), | |
item: this.text | |
} | |
this.$pouchdbRefs.todos.put(todo) | |
} | |
} | |
}) |
Initializing a plugin
A Vue.js plugin should expose an install method. The method will be called with the Vueconstructor as the first argument, along with possible options.
function install(Vue,options){ | |
} |
Defining a Mixin
Mixins are a flexible way to distribute reusable functionalities for Vue components.
var PouchMixin = { | |
beforeCreate: init | |
} |
Note the beforeCreate property. This is an event that gets emitted by vuejs before the initialization of the vue instance properties and methods. The init is a function which you will be creating next.
function init(){ | |
var bindings = this.options.pouchdb | |
ensureRef(this) | |
for(var key in bindings){ | |
bind(this,key,bindings[key]) | |
} | |
} |
In the init function we get the pouchdb option that is set in a vue instance. You will use the ensureRef function to set the $pouchdbRefs property which will hold a reference to the PouchDB object.
function ensureRef (vm) { | |
if (!vm.$pouchdbRefs) { | |
vm.$pouchdbRefs = Object.create(null) | |
} | |
} |
Now the interesting part. You will create the bind function which its main responsibility will be to make the data from PouchDB reactive.
function bind(vm,key,source){ | |
var array = [] | |
defineReactive(vm,key,array) | |
vm.$pouchdbRefs[key] = source // set the refs to refrence the new PouchDB('') passed | |
// PouchDB events | |
source.changes({ | |
since:'now', | |
live: true, | |
include_docs: true | |
}).on('complete',function(info){ | |
}).on('change',function(change){ | |
vm[key].push(change.doc) // this is just an example of how the change can be used. | |
}).on('err',function(err){ | |
}) | |
// end of PouchDB events | |
//Obtaining data from PouchDB | |
source.allDocs({ | |
include_docs: true, | |
descending: true | |
}).then(function(doc){ | |
var docs = doc.rows.map(function(obj){ | |
return obj.doc | |
}) | |
defineReactive(vm,key,docs) | |
}).catch(function(err){ | |
}) | |
} |
One last thing you need to do is notify Vue that it should track changes made on the PouchDB data. The defineReactive function will be responsible for that part. You will use the util from vue to define the reactivity.
function defineReactive(vm,key,val){ | |
// first check if it is present on the vue instance | |
if(key in vm){ | |
vm[key] = val | |
} else { | |
Vue.util.defineReactive(vm,key,val) | |
} | |
} |
Bringin it all together
var init = function(){ | |
var bindings = this.$options.pouchdb | |
ensureRef(this) | |
for(var key in bindings) { | |
bind(this,key,bindings[key]) | |
} | |
} | |
function ensureRef (vm) { | |
if (!vm.$pouchdbRefs) { | |
vm.$pouchdbRefs = Object.create(null) | |
} | |
} | |
function defineReactive(vm,key,val){ | |
if(key in vm){ | |
vm[key] = val | |
} else { | |
Vue.util.defineReactive(vm,key,val) | |
} | |
} | |
function bind(vm,key,source){ | |
var array = [] | |
defineReactive(vm,key,array) | |
vm.$pouchdbRefs[key] = source | |
source.changes({ | |
since:'now', | |
live: true, | |
include_docs: true | |
}).on('complete',function(info){ | |
}).on('change',function(change){ | |
vm[key].push(change.doc) | |
}).on('err',function(err){ | |
}) | |
source.allDocs({ | |
include_docs: true, | |
descending: true | |
}).then(function(doc){ | |
var docs = doc.rows.map(function(obj){ | |
return obj.doc | |
}) | |
defineReactive(vm,key,docs) | |
}).catch(function(err){ | |
}) | |
} | |
var PouchMixin = { | |
init: init, // making it usable with vuejs 1.x.x | |
beforeCreate: init | |
} | |
function install(Vue){ | |
Vue.mixin(PouchMixin) | |
} | |
// auto install | |
if (typeof window !== 'undefined' && window.Vue) { | |
install(window.Vue) | |
} |
You can find the project at github contributions are welcomed.
Top comments (0)