0.1.1 • Published 8 years ago

vs-violet v0.1.1

Weekly downloads
2
License
MIT
Repository
github
Last release
8 years ago

为什么要搞这个vs-violet

因为写一堆reducer太烦了

很多的reducer都是简单的进行赋值,我希望能够将各种情况用指定的文法描述出来,目标是减少绝大部分的只是用来赋值reducer。

怎么用

目前的版本基于dva,我认为dva是对redux一种不错的实践,当然经过简单的改造也可以支持redux,这个事情可以以后在做。

QuickStart

  • Step0 npm install vs-violet

  • Step1 in component

import {violet} from 'vs-violet';
import {connect} from 'dva';

function IndexPage({example, violet}) {
    return <div>hello world</div>;
}

const WarpComponent = violet(IndexPage, {modelName: 'example'});
export default connect((example) => example)(WarpComponent);
  • Step2 in reducer(或者说in dva model)
import {set} from 'vs-violet';

reducers: {
    set
}
  • Step3 try it

现在在你的component内部可以通过violet.set来做赋值了

当你点击test按钮后,state.example.user.group.name就会赋值为groupName

function IndexPage({example, violet}) {
    return <button onClick={e => violet.set('user.group.name', 'groupName')}>test</button>;
}

api

赋值

violet.set(pathArgs, actionArg)

属性类型默认值说明
pathArgsstring|Selector|Matcher-指定最终的赋值位置
actionArgstring | Action-赋值或者要进行的操作

如上表格,violet.set通过一系列的输入定位要操作的位置,然后通过最后一个参数来进行赋值。

  • 简单赋值
violet.set('user.group.name', 'groupName');

将groupName赋值给user'group',在按路径寻找的过程中如果值为undefined,会为其赋值{}

  • 当某一个位置的对象希望是数组时
violet.set('user.groups.[0].name');

当user'groups'不存在时,会将其初始化为[]

  • 当路径中包含.或者[或者与其他语义冲突时
import {selectObj, selectArr} from 'vs-violet';

violet.set('props', selectObj('db.url'), 'jdbc://127.0.0.1');
violet.set('props', selectArr('db.clusters'), [0], '127.0.0.1');

显然,selectObj创建的是object, selectArr创建的是array。

但是当Selector之后马上就是actionArg时,会直接为其赋值,此时两者的效果是相同的。

检测语义冲突的字符串: (.*=.*|\[.*|.*\..*)

  • 在Object的props中查找
import {match, self} from 'vs-violet';

violet.set('userMap', match('name', 'shiki'), 'selected', true);
violet.set('userMap', match(self, 'shiki'), 'selected', true);

等价于

for(const key of Object.keys(userMap)){
    if(userMap[key].name === 'shiki'){
        userMap[key].selected = true;
        break;
    }
}

for(const key of Object.keys(userMap)){
    if(userMap[key] === 'shiki'){
        userMap[key].selected = true;
        break;
    }
}

如果要比较对象自身,则match的第一个参数传self标记。

不同于Selector,当matcher找不到结果时不会做赋值操作,而是直接终止此次set的行为,也就是说在matcher之后的动作都不会触发。以下的Matcher同理。

  • 在Array的elements中查找
import {match} from 'vs-violet';

violet.set('users', match('name', 'shiki'), 'nuked', true);

等价于

(users.find(({name}) => name === 'shiki') || {}).nuked = true;
  • 简化版Matcher
violet.set('users.name=shiki.nuked', 'nuked', true);

如果key或者value中有=,请使用match

  • 自定义查找
import {match} from 'vs-violet';

violet.set('users', match(users => users.find(user => user.id === 4600)), 'removed', true);

要注意的有两点,一是你返回的应当是输入参数中的一个引用,或者说从store的根部到返回的对象是联通的,否则这次set的行为不会体现在store上。

二是自定义查找不能直接与Action相邻,Action的实现需要知道要remove的内容与store相连接的关系,自定义查找没办法将这种关系暴露给框架。

  • 删除一个路径
import {remove} from 'vs-violet';

violet.set('props.[3]', remove());

violet.set({pathArg: actionArg})

批量赋值,pathArg必须是string

更新记录

2017-09-14 v0.1.1

  • 提供字符串中的match语义
  • 简化了match的api
  • 增加了批量赋值的api