欢迎使用Basestone
Basestone
是一个JavaScript常用的数据结构集合,包含了ECMASCript 6 中出现的新特性,比如Map
、Set
等新的数据结构以及一些方便的方法(keys
、values
)等等。
往往我们在处理一些较为复杂的业务逻辑时,从UI binding
开始写起,很多业务逻辑都写在事件的回调函数之中,这往往会造成代码的冗余和逻辑混乱,Basestone目的就是提供一个具有事件特性的常用数据结构,来帮助前端工程师,把界面操作和业务逻辑解耦出来,相当于提供一个数据Model
中间层。
EventEmitter
EventEmitter
为Basestone
提供了一个简洁事件模型,接口完全兼容Node
的event.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中的基础类型数据,比如说Number
、String
等,可以对值进行修改,修改后会有相应的事件触发,可以提供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,即对内部有修改的方法:
- pop
- push
- reverse
- shift
- sort
- splice
- unshit
Accessor,即读取方法:
- concat
- join
- slice
- indexOf
- lastIndexOf
Iteration,迭代方法:
- forEach
- every
- some
- filter
- map
- reduce
- reduceRight
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
当键值有改变时,会触发该事件。