dataton

1.6.7 • Public • Published

Build Status

Dataton

一个简单的基于cursor的状态对象实现。

install

npm install dataton

Example

var State = require('dataton');
// 任意一个cursor导致的更新都将让state内部的指针指向新的状态
// 且之后的cursor返回值都是基于这个新的状态的路径的值
var state = new State({
       name: 'jack',
       profile: {
               gender: 'male'
           }
});
 
// 通过cursor方法得到cursor
var nameCursor = state.cursor('name');
var profileCursor = state.cursor('profile');
var genderCursor = state.cursor('profile.gender');
 
// 通过调用cursor函数得到cursor对应的值
assert.equal(nameCursor(), 'jack');
assert.equal(genderCursor(), 'male');
 
// 通过调用cursor的update方法,更新其对应值
nameCursor.update('john');
// 如果只想更新其部分值,可传入路径。
profileCursor.update('gender', 'female'); 
// 如果想对对象内部进行操作,可传入函数
// 其返回值将被设成要更新的值
profileCursor.update(function(profile) {
  profile.name = "benson";
  profile.gender = "female";
  return profile;
});
 
// 能过调用cursor函数获得已经更新的值
assert.equal(nameCursor(), 'john');
assert.equal(genderCursor(), 'female');

API

State

cursor(path)

  • path 数组或字符串,表示cursor指定的路径。

返回一个cursor,永远指向state的path路径。

var state = new State({
    profile: {
        name: 'jack'
    },
    "big.secret": {
        key: "open-the-door"
    }
});
// path 可以是以点分隔的路径
var cursor = state.cursor('profile.name');
assert.equal(cursor(), 'jack');
 
// path可以是数组
var cursor = state.cursor(['big.secret', 'key']);
assert.equal(cursor(), 'open-the-door');

load(obj)

将state的内部数据更新为obj。

get(path)

读取state的path路径上的数据,若路径不存在则返回undefined. path可以是字符串或数据。

var state = new State();
state.load({name: 'jack'}); // 通过load加载
assert.equal(state.get('name'), 'jack'); // 通过get获取

set(path, value)

更新path路径上的值为value

var state = new State();
state.load({name: 'jack'});
state.set('name', 'john'); // 修改为john了
assert.equal(state.get('name'), 'john'); 

toJS()

将state的内部数据输出为JSON对象供调试及读取。

on(eventName, callback)

监听事件,通常用于监听state的change事件。

Cursor

@self()

一个cursor本身就是一个函数,调用自身将返回其游标对应的数据。

var state = new State();
state.load({name: 'jack'});
var cursor = state.cursor('name');
assert.equal(cursor(), 'jack');

get(path)

path可是字符串也可是数组,表示要取值的相对路径。使用get方法是非常安全的,因为get方法并不会因为path不存在而抛出异常。

var state = new State();
state.load({
    profile: {
        name: "jack",
        age: 10,
        parent: {
            mother: {
                name: 'nina'
            },
            father: {
                name: 'chris'
            }
        }
    }
});
var cursor = state.cursor('profile');
assert.equal(cursor.get('parent.mother.name'), 'nina');
// 路径不存在,直接返回undefined
// 如果写成: cursor().some.other.path 将出错。
assert.equal(cursor.get('some.other.path'), undefined);

update(path, sth) 或 update(sth) 或 update(function)

更新cursor对应路径上的值。

var state = new State();
state.load({
    profile: {
        name: "jack",
        age: 10,
        parent: {
            mother: {
                name: 'nina'
            },
            father: {
                name: 'chris'
            }
        }
    }
});

var cursor = state.cursor('profile');
// 更新指定路径上的值
cursor.update('parent.mother.name', 'rose');
assert.equal(cursor().parent.mother.name, 'rose');
// 更新整个cursor对应的值
cursor.update({name: 'monkey'});
assert.equal(cursor().name, 'monkey');
assert.equal(cursor.get('parent.mother.name'), undefined);

// 通过传入函数,更新整个cursor对应的值
cursor.update(function(profile) {
  profile.name = 'mm';
  profile.parent.mother.name = 'sarah';
  return profile; // do not forget this line
});
assert.equal(cursor().name, 'mm');
assert.equal(cursor.get('parent.mother.name'), sarah);

cursorFromObject(obj)

通过传入一个对象,来查找到它对应的cursor, 进而修改这个路径上的内容。 注意:必需是一个对象,不能是基本类型数据。

var state = new State();
state.load({
  profile: {
    name: 'jack',
    age: 18
  }
});

var profile = state.get('profile');
var profilecursor = state.cursorFromObject(profile);

cursor.update('name', 'john');
assert.equal(state.get('profile.name'), 'john');

mergeUpdate(obj)

将obj中所有键的路径,更新到cursor对应的值上, 这是一个深度merge。

var state = new State();
state.load({
    profile: {
        name: "jack",
        age: 10,
        parent: {
            mother: {
                name: 'nina'
            },
            father: {
                name: 'chris'
            }
        }
    }
});

var cursor = state.cursor('profile');
// 更新指定路径上的值
cursor.mergeUpdate({
    parent: {
        mother: {
            name: 'coffee'
        }
    }
});

// 更新后的cursor()值为:
{
    parent: {
        mother: { name: 'coffee' }
        father: { name: 'chris' }
    }
}

namespace(path)

命名空间,如果我们的一些cursor的前缀是一样的,那么最好采用命名空间节省代码量。如:

var state = new State();
state.load({
    profile: {
        name: "jack",
        age: 10,
        parent: {
            mother: {
                name: 'nina'
            },
            father: {
                name: 'chris'
            }
        }
    }
});

// 设定一个命名空间
var ns = state.namespace('profile');

// 从命名空间开始查找cursor路径
var nameCursor = ns.cursor('name'); // 相当于state.cursor('profile.name');
var fatherCursor = ns.cursor('parent.father'); // 相当于state.cursor('profile.parent.father')

assert.equal(nameCursor(), 'jack');
assert.equal(fatherCursor().name, 'chris');

事件

dataton的实例会在不同阶段发出不同事件. 当调用set或cursor的update方法成功更新指定路径上的对象时. 会emit出change和update事件,可以通过state.on('change, callback). 或state.on('update', callback)来监听.

  • change事件的callback不应该有参数。
  • update事件的callback可有一个参数,这个参数是一个JS Object, 有如下属性:
    • host: 即宿主对象state
    • path: 更新的路径
    • oldval: 原始值
    • newval: 新值

dataton实例将在不同时段emit出相应的message事件, 方便用户debug.

注意

  • 如果一个cursor的值是引类型, 千万不要直接修改其对应值,应当生成一个新值然后传给其update.
  • 不应该在dataton实例里存储非Object, Array和基础类型的值. 如果确真需要,可以state.config("SKIP_TYPE_CHECK", true)

License

MIT

Readme

Keywords

Package Sidebar

Install

npm i dataton

Weekly Downloads

20

Version

1.6.7

License

MIT

Last publish

Collaborators

  • ssnau