Javascript 使用Ramdajs将命令式转换为函数式范式
下面的脚本创建了一个过滤一些输入数据的对象。 它使用多个嵌套的Javascript 使用Ramdajs将命令式转换为函数式范式,javascript,functional-programming,lodash,ramda.js,Javascript,Functional Programming,Lodash,Ramda.js,下面的脚本创建了一个过滤一些输入数据的对象。 它使用多个嵌套的forEach以声明方式编码 我想知道在重写代码时使用哪个API,或者,特别是我想了解在本例中使用的是否合适 请举一个代码示例(特别是ramdajs)。谢谢 var数据={ “类型”:“样式表”, “样式表”:{ “规则”:[{ “类型”:“关键帧”, “名称”:“弹跳”, “关键帧”:[{ “类型”:“关键帧”, “价值观”:[ “从”, "20%", "53%", "80%", “到” ], “声明”:[{ “类型”:“声明”,
forEach
以声明方式编码
我想知道在重写代码时使用哪个API,或者,特别是我想了解在本例中使用的是否合适
请举一个代码示例(特别是ramdajs)。谢谢
var数据={
“类型”:“样式表”,
“样式表”:{
“规则”:[{
“类型”:“关键帧”,
“名称”:“弹跳”,
“关键帧”:[{
“类型”:“关键帧”,
“价值观”:[
“从”,
"20%",
"53%",
"80%",
“到”
],
“声明”:[{
“类型”:“声明”,
“属性”:“动画计时功能”,
“值”:“立方贝塞尔(0.215,0.610,0.355,1.000)”,
“职位”:{
“开始”:{
"行":3,,
“栏”:5
},
“结束”:{
"行":3,,
“栏”:72
}
}
}, {
“类型”:“声明”,
“属性”:“转换”,
“值”:“translate3d(0,0,0)”,
“职位”:{
“开始”:{
"行":4,,
“栏”:5
},
“结束”:{
"行":4,,
“栏”:34
}
}
}],
“职位”:{
“开始”:{
"线":2,,
“专栏”:3
},
“结束”:{
“行”:5,
“专栏”:4
}
}
}, {
“类型”:“关键帧”,
“价值观”:[
"40%",
"43%"
],
“声明”:[{
“类型”:“声明”,
“属性”:“动画计时功能”,
“值”:“立方贝塞尔(0.755,0.050,0.855,0.060)”,
“职位”:{
“开始”:{
“行”:8,
“栏”:5
},
“结束”:{
“行”:8,
“栏”:72
}
}
}, {
“类型”:“声明”,
“属性”:“转换”,
“值”:“translate3d(0,-30px,0)”,
“职位”:{
“开始”:{
“行”:9,
“栏”:5
},
“结束”:{
“行”:9,
“专栏”:40
}
}
}],
“职位”:{
“开始”:{
“行”:7,
“专栏”:3
},
“结束”:{
“行”:10,
“专栏”:4
}
}
}, {
“类型”:“关键帧”,
“价值观”:[
"70%"
],
“声明”:[{
“类型”:“声明”,
“属性”:“动画计时功能”,
“值”:“立方贝塞尔(0.755,0.050,0.855,0.060)”,
“职位”:{
“开始”:{
“行”:13,
“栏”:5
},
“结束”:{
“行”:13,
“栏”:72
}
}
}, {
“类型”:“声明”,
“属性”:“转换”,
“值”:“translate3d(0,-15px,0)”,
“职位”:{
“开始”:{
“行”:14,
“栏”:5
},
“结束”:{
“行”:14,
“专栏”:40
}
}
}],
“职位”:{
“开始”:{
“行”:12,
“专栏”:3
},
“结束”:{
“行”:15,
“专栏”:4
}
}
}, {
“类型”:“关键帧”,
“价值观”:[
"90%"
],
“声明”:[{
“类型”:“声明”,
“属性”:“转换”,
“值”:“translate3d(0,-4px,0)”,
“职位”:{
“开始”:{
“行”:18,
“栏”:5
},
“结束”:{
“行”:18,
“专栏”:37
}
}
}],
“职位”:{
“开始”:{
“行”:17,
“专栏”:3
},
“结束”:{
“行”:19,
“专栏”:4
}
}
}],
“职位”:{
“开始”:{
"线":一,,
“栏”:1
},
“结束”:{
“行”:20,
“专栏”:2
}
}
}, {
“类型”:“规则”,
“选择器”:[
“.bounce”
],
“声明”:[{
“类型”:“声明”,
“属性”:“动画名称”,
“值”:“反弹”,
“职位”:{
“开始”:{
“行”:23,
“专栏”:3
},
“结束”:{
“行”:23,
“栏”:25
}
}
}, {
“类型”:“声明”,
“属性”:“转换原点”,
“值”:“中间-底部”,
“职位”:{
“开始”:{
“行”:24,
“专栏”:3
},
“结束”:{
“行”:24,
“栏”:34
}
}
}],
“职位”:{
“开始”:{
“行”:22,
“栏”:1
},
“结束”:{
“行”:25,
“专栏”:2
}
}
}, {
“类型”:“关键帧”,
“名称”:“火花”,
“克
transformAST
^
|
|
getContentOfKeyframes
^ ^
| |
| |
processKeyframe processAnimation
var processKeyframe = (vals, declarations) => [
// map each value
R.map(R.cond([
[R.equals('from'), R.always(0)],
[R.equals('to'), R.always(100)],
[R.T, parseFloat]
]), vals),
// collect all property value pairs and merge in one object
R.reduce(R.merge, {},
R.map(R.converge(R.objOf, [
R.prop('property'),
R.prop('value')
]), declarations))
]
var processAnimation = (offsets, transf) =>
R.map(R.pipe(
R.objOf('offset'),
R.merge(transf)), offsets)
var getContentOfKeyframes = R.map(R.pipe(
// process keyframes
R.converge(processKeyframe, [
R.prop('values'),
R.prop('declarations')
]),
// process animations
R.converge(processAnimation, [
R.nth(0),
R.nth(1)
])))
var transformAST = R.pipe(
// get `stylesheet.rules` property
R.path(['stylesheet', 'rules']),
// get only object whose `type` property is `keyframes`
R.filter(R.propEq('type', 'keyframes')),
// map each item in `keyframes` collection
// to an object {name: keyframe.name, content: [contentOfkeyframes] }
R.map((keyframe) => ({
name : keyframe.name,
content : getContentOfKeyframes(keyframe.keyframes)
})),
// finally make a new object using animation `name` as keys
// and using a flatten content as values
R.converge(R.zipObj, [
R.map(R.prop('name')),
R.map(R.pipe(R.prop('content'), R.flatten))
]))
var result = transformAST(data)
var processKeyframe = (vals, declarations) => [
R.map(R.cond([
[R.equals('from'), R.always(0)],
[R.equals('to'), R.always(100)],
[R.T, parseFloat]
]), vals),
R.reduce(R.merge, {},
R.map(R.converge(R.objOf, [
R.prop('property'),
R.prop('value')
]), declarations))
]
var processAnimation = (offsets, transf) =>
R.map(R.pipe(
R.objOf('offset'),
R.merge(transf)), offsets)
var getContentOfKeyframes = R.map(R.pipe(
R.converge(processKeyframe, [
R.prop('values'),
R.prop('declarations')
]),
R.converge(processAnimation, [
R.nth(0),
R.nth(1)
])))
var transformAST = R.pipe(
R.path(['stylesheet', 'rules']),
R.filter(R.propEq('type', 'keyframes')),
R.map((keyframe) => ({
name : keyframe.name,
content : getContentOfKeyframes(keyframe.keyframes)
})),
R.converge(R.zipObj, [
R.map(R.prop('name')),
R.map(R.pipe(R.prop('content'), R.flatten))
]))
var result = transformAST(data)
const transform = pipe(
path(['stylesheet', 'rules']),
filter(where({'type': equals('keyframes')})),
groupBy(prop('name')),
map(map(kf => map(kfi => map(v => assoc('offset', cond([
[equals('from'), always(0)],
[equals('to'), always(100)],
[T, parseFloat]
])(v), pipe(
map(lift(objOf)(prop('property'), prop('value'))),
mergeAll
)(kfi.declarations)), kfi.values), kf.keyframes)
)),
map(flatten)
);
{
bounce: [obj1, obj2, ...]
spark: [objA, objB, ...]
}
map(v => map(lift(objOf)(prop('property'), prop('value'))), kfi.declarations)
[
{"animation-timing-function": "cubic-bezier(0.215, 0.610, 0.355, 1.000)",}
{transform: "translate3d(0,0,0)"},
]
cond([
[equals('from'), always(0)],
[equals('to'), always(100)],
[T, parseFloat]
])(v)
{
"animation-timing-function": "cubic-bezier(0.215, 0.610, 0.355, 1.000)",
offset: 0,
transform: "translate3d(0,0,0)"
}
{
bounce: [[[obj1, obj2, ...]]]
spark: [[[objA, objB, ...]]]
}