为什么要搞这个vs-violet
因为写一堆reducer太烦了
很多的reducer都是简单的进行赋值,我希望能够将各种情况用指定的文法描述出来,目标是减少绝大部分的只是用来赋值reducer。
怎么用
目前的版本基于dva,我认为dva是对redux一种不错的实践,当然经过简单的改造也可以支持redux,这个事情可以以后在做。
QuickStart
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
}
现在在你的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)
属性 | 类型 | 默认值 | 说明 |
---|
pathArgs | [string|Selector|Matcher] | - | 指定最终的赋值位置 |
actionArg | string | Action | - | 赋值或者要进行的操作 |
如上表格,violet.set通过一系列的输入定位要操作的位置,然后通过最后一个参数来进行赋值。
violet.set('user.group.name', 'groupName');
将groupName赋值给user['group']['name'],在按路径寻找的过程中如果值为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时,会直接为其赋值,此时两者的效果是相同的。
检测语义冲突的字符串: (.*=.*|\[.*|.*\..*)
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同理。
import {match} from 'vs-violet';
violet.set('users', match('name', 'shiki'), 'nuked', true);
等价于
(users.find(({name}) => name === 'shiki') || {}).nuked = true;
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