欢迎使用Basestone

Basestone是一个JavaScript常用的数据结构集合,包含了ECMASCript 6 中出现的新特性,比如MapSet等新的数据结构以及一些方便的方法(keysvalues)等等。

往往我们在处理一些较为复杂的业务逻辑时,从UI binding开始写起,很多业务逻辑都写在事件的回调函数之中,这往往会造成代码的冗余和逻辑混乱,Basestone目的就是提供一个具有事件特性的常用数据结构,来帮助前端工程师,把界面操作和业务逻辑解耦出来,相当于提供一个数据Model中间层。

EventEmitter

EventEmitterBasestone提供了一个简洁事件模型,接口完全兼容Nodeevent.EventEmitter。也可单独使用。

var target = {}
basestone.util.extend(target, basestone.EventEmitter.prototype)
// 现在 `target` 就可以绑定或触发事件了。
AddListener(event, listener)
on(event, listener)

注册一个名为event的事件监听器,监听器会依照执行的顺序依次执行。

// same as target.on
target.addEventListener('finish', function () {
    console.log("finished")
})
once

注册一个名为event的事件监听器,且该监听器只执行一次。

target.once('done', function () {
    console.log("task is done")
})
removeListener(event, listener)

删除注册到event下面的事件监听器listener

// like target.once
var
finishHandler = function () {
    console.log('task has finished')
    target.removeListener('finish', finishHandler)
}
target.on('finish', finishHandler)
removeAllListeners([event])

移除event下面所有监听器,如果没有传入event,移除所有的监听器。

setMaxListeners(n)

设置某个具体事件的最大监器个数,默认值为10。

listeners(event)

获取event下面的所有监听器。

emit(event, [arg1, [arg2] ...])

触发事件event,可以传递一些参数。

target.on('finish', function (time) {
    console.log(time + ":finished")
}
target.emit('finish', Date.now)

value

value可用来存储JavaScript中的基础类型数据,比如说NumberString等,可以对值进行修改,修改后会有相应的事件触发,可以提供State的功能。

contructor

可以用来构造一个vlaue,或者改变值。

var
step = backbone.value(1)
// 改到步骤2
step(2)
// 回到步骤1
step(1)

var
// st等于1
st = step()
"change"

值改变时,会触发change事件。可以把散落在各个UI事件回调中的业务逻辑放到Model的回调中,组织起来,没有重复的代码。

step.on('change', function(st) {
    if (st === 1) {
        // 显示表单
    } else if (st === 2) {
        // 收起表单 显示结果
    } else {
        // 做点别的事
    }
})

// 表单中的submit
submit.on('click', function () {
    // 业务处理,成功后
    step(2)
})

back.on('click', function () {
    // 返回修改表单
    step(1)
})

object

可以把object想象成JavaScript中Object对象的包装器,是用来管理一簇属性的,相当于Backbone中的Model类。属性值改变时,会触发相应的事件

constructor
var task
task = backbone.object({
    content:'email to Mis',
    createTime:'Thu Jan 10 2013 14:36:11 GMT+0800 (中国标准时间)'
})
// "email to Mis"
task('content')

task('content', 'email to Mr')

// {content: 'email to Mr', createTime: 'Thu Jan 10 2013 14:36:11 GMT+0800 (中国标准时间)'}
task()
keys([iterator])

返回一个数组,包含所有的key,如果传了iterator,就迭代每一个key

// ['content', 'createDate']
task.keys()

// email to Mr
// Thu Jan 10 2013 14:36:11 GMT+0800 (中国标准时间)
task.keys(function (key) {
    console.log(task(key))
})
"change"

当属性的值变化时,会触发"change"事件。

task.on('change', function () {
    console.log('something changed')
})
task('content', 'email to Ms')
"change:key"

可指定监听"change"事件的属性。

task.on('change:createDate', function (val) {
    console.log('Create Date change to ' + val)
})
task('createDate', new Date())

array

可以把array想想成JavaSscript的Array对象的包装器,相当于Backbone中的Collection类,但没有那么强,用来管理一系列的项目。

constructor

可以传递一个数组作为初始化的项。

var memo
memo = basestone.array([task1, task2, task3])
memo(0)                     // task1
memo()                      // new Array containing task1, task2, task3
memo([task4, task5, task6]) // or just reset it
Array.prototype

memo对象上包含所有Array上常用的一些原型方法,包括新标准中加入进来的,大致分成三类:

Mutator,即对内部有修改的方法:

Accessor,即读取方法:

Iteration,迭代方法:

var memo
memo = basestone.array([task1, task2, task3])
memo.pop() // task3
memo(memo.concat([task4, task5])) // memo now is [task1, task2, task3, task4, task5]
memo.forEach(function (task) {
    task.done = true
})
var
isDone = memo.every(function (task) {
    return task.done === true
})
"change"

当Mutator方法被调用时,会对内部进行修改,此时会触发"change"事件。

memo.on('change', function () {
    console.log('memo is changed')
    // rerender UI by memo.forEach
})
"[method]"

Mutator方法被调用时,会触发以相应方法名的事件。

memo.on('push', function () {
    // do something when there is item push in array
})

set

Set作为ECMAScript 6草案新添加的数据结构,有其自身的特点和需要。可用来管理一组值,而不用关系这组值的类型和内容,且每个值都是唯一的。set即是对它的实现。

var
store
store = basestone.set()

store.add(null)
store.add(undefined)
store.add(1)
// there are `null` `undefined` `1` in store

store.add(undefined)
// there are still `null` `undefined` `1` in store
contructor

可传递一组初始值,初始值甚至可以是重复的,也可以什么都不传。

var
nameList
nameList = basestone.set(['Devid', 'Lucy', 'Lily', 'Derek', 'Lucy'])
// ['Devid', 'Lucy', 'Lily', 'Derek']
console.log(nameList.values())
add

把更多的值添加到`Set`中,可以添加已经存在的值,只是`Set`本身没什么变化。

nameList.add('Island')
nameList.add('Devid')
// ['Devid', 'Lucy', 'Lily', 'Derek', 'Island']
console.log(nameList.values())
remove

删除`Set`中存在的项,返回`true`,如果不存在删除项,则返回`false`。

nameList.remove('Island')
// `false`
console.log(nameList.remove('Man'))
has

查看是否存在某个值。

// true
nameList.has('Devid')
values

把所有的值作为一个数组返回,如果传入迭代器,则迭代所有的值。

nameList.values(function (name) {
    console.log(name + ' is here!')
})
"add" event

有新值加入进来时,会触发"add"事件。

nameList.on('add', function (name) {
    console.log(name + ' is added!')
})
// 'Rose is added!'
nameList.add('Rose')
"remove" event

删除值时会触发"remove"事件。

nameList.on('remove', function (name) {
    console.log(name + ' is removed!')
})
// 'Devid is removed!'
nameList.remove('Devid')
"change" event

不管是新增还是删除值,只要是对`Set`进行修改时,都会触发"change"事件。

nameLiist.on('change', function () {
    // rerender name list UI
})

map

ECMAScript 6还引入了另外一种数据结构——Map,与Object的不同之处在于,Map可以使用任何值作为key,而Object只能使用字符串作为key。而这里的map就是对其实现。

constructor

可传递一个二维数组,初始化一个map

var
mp
mp = basestone.map([[undefined, undefined], [null, null], [document.body, document.body]])
// undefined
mp.get(undefined)
// or just
mp(undefined)
set

添加或者修改某个键值对。

mp.set(document.body, 'document.body')
// 'document.body'
mp.get(document.body)
remove

删除某个键值对。

mp.remove(document.body)
// undefined
mp.get(document.body)
get

获取值。

// null
mp.get(null)
// or just
mp(null)
has

查看是否存在某个值。

// false
mp.has(document.body)
keys

把全部键作为一个数组返回,如果传递一个函数作为迭代器的话,会迭代每一个键。

// [undefined, null]
mp.keys()

// or iterate them
mp.keys(function (key) {
    // do with key
})
values

keys类似,不过迭代的是值。

// [undefined, null]
mp.values()

// or
mp.values(function (value) {
    // do with value
})
"remove" event

当删除键值对时,会出发该事件。

"change" event

当键值有改变时,会触发该事件。