由于之前项目中为了最求最大灵活度,部分功能预留了JavaScript脚本配置入口,如有特殊需求的情况下可不修改代码实现个性化需求。
例如:报表设计中的图形组件,可能不同的报表展示形式多样,此时的界面配置无法提前预设所有可能的情况,如果在图形渲染将前端生成的配置参数交给预先配置好的JavaScript脚本进行特殊处理就可以完成个性需求。但该功能需要动态执行JavaScript脚本,前端只能通过eval
Function
方式来动态执行,这种运行方式在浏览器模式下是没问题,但在不支持eval
Function
的运行环境就无法实现上述需求,例如:微信小程序。
eval5是完全基于JavaScript编写的JavaScript解释器,支持ECMA5语法。
项目地址:https://github.com/bplok20010...
在线体验:https://bplok20010.github.io/...
步骤一:eval5先通过acorn
将源码编译得到树状结构的抽象语法树(AST)。
抽象语法树由不同的节点组成,每个节点的type标识着不同的语句或表达式,例如: 1+1的抽象语法树:
{ "type": "Program", "body": [ { "type": "ExpressionStatement", "expression": { "type": "BinaryExpression", "operator": "+", "left": { "type": "Literal", "value": 1, "raw": "1" }, "right": { "type": "Literal", "value": 1, "raw": "1" } } } ], "sourceType": "script" }
步骤二:为不同的节点type编写不同的处理模块并得到最终结果。例如:根据1+1的语法树我们可以写出一下解释器代码:
function handleBinaryExpression(node) { switch( node.operator ) { case '+': return node.left.value + node.right.value; case '-': return node.left.value - node.right.value; } }
生成抽象语法树
这一步已经有很多优秀的开源库,如:esprima
acorn
babylon
...
步骤二执行大概如下:
type
执行对应的处理方法,并得到最后一个表达式返回值。例如BinaryExpression
节点则调用handleBinaryExpression
方法更多实现细节就不详细讲解,有兴趣的可直接到github上看源码。
需要注意的两点:
可将es5代码直接粘贴到文章开头的体验地址并运行查看效果。以下是运行echarts的效果示例:
//设置在线体验容器高度 root.style.height = '300px'; // 基于准备好的dom,初始化echarts实例 var myChart = echarts.init(document.getElementById('root')); // 指定图表的配置项和数据 var option = { title: { text: 'ECharts 入门示例' }, tooltip: {}, legend: { data: ['销量'] }, xAxis: { data: ["衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子"] }, yAxis: {}, series: [{ name: '销量', type: 'bar', data: [5, 20, 36, 10, 10, 20] }] }; // 使用刚指定的配置项和数据显示图表。 myChart.setOption(option);
效果如图:
不支持eval
Function
的运行环境,例如:微信小程序,小程序开发用户可直接看这篇介绍:小程序eval/Function终极替代方案:eval5