本文是《前端大屏原理系列》第四篇:创建动态函数。
本系列所有技术点,均经过本人开源项目 react-big-screen 实际应用,欢迎 star (*´▽`)ノノ.
一、效果演示
二、实现原理
运行时创建函数主要为了修改组件传递参数的数据格式,或者实现一些更复杂的处理逻辑。因为大屏多组件联动传输的数据格式是固定的,通过函数转换数据格式可以兼容更多组件,而无需修改源代码。常见的js创建动态函数方式有两种:eval
、new Function
。(我们最终要实现的目标是:动态创建 main 函数。)
本项目使用 new Function 实现,eval 存在安全问题不推荐!
2.1 eval
eval 主要用来执行一段js代码,其可以读取、修改「调用作用域」,因此是不安全的。风险如下:
// 风险一:获取调用作用域
const name = "xxx";
eval("console.log(name)") // xxx
// 风险二:修改调用作用域
let name = "xxx";
eval("name = '222'")
console.log(name) // 222
下面是创建main函数的实现代码:
const text = `
let len = 5;
function main () {
return Array(len).fill(1);
}
`
// 使用匿名函数创建局部作用域,避免与调用作用域中的变量同名导致报错。
function getMainByEval(text: string): Function | undefined {
let fn;
eval(`(() => {
${text};
fn = main;
})()`)
return fn;
}
// 测试函数
const createArray = getMainByEval(text);
console.log(createArray()); // [1,1,1,1,1]
2.2 new Function
调用 Function
的构造函数创建动态函数,其会在全局作用域创建闭包,所以只能访问「自身局部作用域」或「全局作用域」。其不能读取、修改当前「调用作用域」,因此比eval
更安全。实现代码如下:
function getMainByFunction(text: string): Function | undefined {
return new Function(`${str}; return main;`)();
}
// 测试
const createArray = getMainByFunction(text);
console.log(createArray()); // [1,1,1,1,1]
【前端大屏原理系列】
react-big-screen 是一个从0到1使用React开发的前端拖拽大屏开源项目。此系列将对大屏的关键技术点一一解析。包含了:拖拽系统实现、自定义组件、收藏夹、快捷键、可撤销历史记录、加载远程组件/本地组件、自适应预览页、布局容器组件、多组件联动(基于事件机制)、成组/取消成组、多子页面切换、i18n国际化语言、鼠标范围框选、... ... 等等。
演示地址:点击访问