backbone@next implemented with plain old javascript with minimal dependencies
Callback
is the event system in pojs
. it is used for module-to-module or module-to-collection communication
Callback.on(event, callback, [context])
Bind a callback function to an object. The callback will be invoked whenever the event is fired. If you have a large number of different events on a page, the convention is to use colons to namespace them: "poll:start", or "change:selection".
Callback.off([event], [callback], [context])
Remove a previously-bound callback function from an object. If no context is specified, all of the versions of the callback with different contexts will be removed. If no callback is specified, all callbacks for the event will be removed. If no event is specified, callbacks for all events will be removed.
Callback.trigger(event, [*args])
Trigger callbacks for the given event. Subsequent arguments to trigger will be passed along to the event callbacks.
purpose of collection
- cache data on client side
- network communication
- communication channel between modules
new Collection([seed], [name], [options])
Collections are ordered sets of models.
inital data to populate collection
prefix of localstorage key, if absent collection wont be saved to localstorage
define options.idAttr
to override the default id
index key
define options.ajax
to override the default ajax
network request function use by collection
define options.cache
to override the default localstorage cache function
Collection constructor only process the first one arguments (seed
), addtional arguments are processed by Collection.init
function.
the default init function
init:function(name, opt){
this.name = name
opt = opt || {}
this.ajax = opt.ajax || this.ajax
this.idAttr = opt.idAttr || this.idAttr
}
collection only cache the data if name
is a valid string
Collection.init
can be overriden by extend
function or inherit
keyword
// in customcollection.js
const Collection = require('po/collection')
Collection.extend({
init:function(jwt){
this.name = 'CustomColl'
this.idAttr = '_key'
this.ajax = function(method,route,params,cb){
if (!route) return cb(null,params)
pico.ajax(method,route,params,{Authorization: 'Bearer' + jwt},function(err,state,res){
if (4!==state) return
if (err) return cb(err)
try{var obj=JSON.parse(res)}
catch(ex){return cb(ex)}
cb(null,obj)
})
}
return true
}
})
// in another.js
const CustomCollection = require('customcollection')
const coll = new CustomCollection(null, {}, jwt); // name, opt arguments are no longer needed in CustomerCollection
if the default ajax function doesn't meet your requirement, for example you need addtional headers. you can override it by passing in a new ajax function
// pico is already defined
function aclosure(jwt){
const options = {
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer ' + jwt
}
}
return {
ajax(method, route, params, cb){
if (!route) return cb(null,params)
pico.ajax(method,route,params,options,function(err,state,res){
if (4!==state) return
if (err) return cb(err)
try{var obj=JSON.parse(res)}
catch(ex){return cb(ex)}
cb(null,obj)
})
}
}
}
const coll = new Collection(null, {}, 'example', aclosure(jwt));
Collection
has Callback
built in.
These are the events supported
- add: when new model added to collection
- update: when an existing model got updated
- delete: when an existing model got deleted
- clear: when the collection got cleared
Example
// in amodule.js
// newModel will be trigger 2 times
function newModel(coll, id){
// this === amodule instance
}
return {
start(opt, coll){
coll.on('add', newModel, this)
coll.create({id: 1, value: 'a'})
coll.create({id: 2, value: 'b'})
}
}
collection.add(models, cb)
Add an array of raw object to the collection, firing an "add" event for each object added to collection as model
const coll = new Colection()
coll.create({id: 1, value: 'a'})
collection.list([filter1], [filter2], cb)
Get all models from a collection. only read from local storage if no filter1 and filter2 passed in
you can specified startId and lastId as filter1 and filter2, list
will return an array models which id in (startId, lastId). list
will trigger network call to upstream to get missing models in local storage
collection.list(1, 100, () => {})
you can also specified array of need id as filter1, list
will return an array models which id in filter1. list
will trigger network call to upstream to get missing models in local storage
collection.list(['dog', 'cat'], () => {})
There are two ways to extend a module
- use the
extend
built in method - use
inherit
keyword, it is synxtax sugar ofrequire
+extend
inherit
is more convenient but.extend
is more flexible it allow you to extend multiple objects in a file
Example:
// CustomModule.js
const Module = require('po/module');
return Module.extend({
start(opt, param1){
Module.prototype.start.call(this, opt);
// extra processing here
}
});
// othermodule.js
const CustomModule = inherit('CustomModule')
return {
start(opt, param1){
CustomModule.prototype.start.call(this, opt, param1);
}
}
Module
has Callback
builtin to support event communication between modules
Example
// module1.js
function onHello(data){
console.log(data) // 'abc'
}
function onWorld(data){
console.log(data) // 'def'
}
return {
start(opt, mod2){
this.peer = mod2
mod2.callback.on('hello', onHello, this)
this.callback.on('world', onWorld, this)
},
go(){
this.peer.callback.trigger('foo', 123)
this.callback.trigger('bar', 456)
}
}
// module2.js
function onFoo(data){
console.log(data) // 123
}
function onBar(data){
console.log(data) // 456
}
return {
start(opt, mod1){
this.peer = mod1
mod1.callback.on('bar', onBar, this)
this.callback.on('foo', onFoo, this)
},
go(){
this.peer.callback.trigger('world', 'def')
this.callback.trigger('hello', 'abc')
}
}
// in parent of module1 and module2
const m1 = new Module1
const m2 = new Module2
m1.start(null, m2)
m2.start(null, m1)
m1.go()
m2.go()
load test/test.html
in browser, result is in console panel