我有一个多页面网站,它使用React作为一个美化的小部件工具包(不同页面上的不同包)。但是,某些窗口小部件状态在登录会话内持续存在当用户重新打开页面时,组件应重新加载其初始状态。我目前这样做:
这看起来很浪费,因为后端已经知道页面是什么,以及小部件的初始状态。所以我考虑渲染初始状态,作为服务页面内的普通对象,让对象在安装时获取它。
我最初的尝试将初始状态表示为:
[some other HTML ... ]
<script>
var WIDGET_INITIAL_STATE = {
startDate: '...',
filters: ['filter1', 'filter2', ... ]
}
</script>
然后在组件设置中使用此全局。当然,这是危险的不安全因为filters
由文本输入控制,所以如果要输入</script> [ arbitrary HTML ] <script>
,上面的内容将变为:
<script>
var WIDGET_INITIAL_STATE = {
startDate: '...',
filters['<script>
[arbitrary HTML]
</script>', 'filter2']
}
</script>
这是灾难性的坏事。
但是,如果我尽职尽责并在服务器端清理它,那么在React中渲染它并不容易,因为传递<script>
形式的字符串会按字面意思呈现,{{3 }}
我认为以这种方式工作的唯一解决方案是在unicode转义时逃避违规字符。
注意:我知道这是非常不正统的,但我希望看到任何更好的选择,如果不是思考练习。
答案 0 :(得分:1)
将filters
数组的内容输出到script
元素时,请执行以下两项操作:
确保它们是正确形成的字符串文字。一种简单的方法是将过滤字符串传递给JSON.stringify
。
确保序列</script>
从不按字面意思发生,这很容易用正则表达式完成。 (这只是必要的,因为您在script
标记的正文中输出这些字符串;如果它们是通过.js
加载的外部src
文件中输入的话,那就不会无所谓。)
例如,对于每个过滤字符串
stringToOutputToFiltersArray = JSON.stringify(filterString.replace(/<\s*\/\s*script\s*>/gm, "<\\/script>"))
// "server side" code
var filters = [
'filter1',
'<script> [arbitrary HTML] </sc' + 'ript>',
'filter3'
];
var inlineScript =
"<script>\n" +
"var WIDGET_INITIAL_STATE = {\n" +
" startDate: '...',\n" +
" filters: [" + filters.map(filter =>
JSON.stringify(filter.replace(/<\s*\/\s*script\s*>/gm, "<\\/script>"))
) + "]\n" +
"};\n" +
"</sc" + "ript>";
document.write(inlineScript);
console.log("filters:", filters);
console.log("inlineScript:", inlineScript);
console.log("WIDGET_INITIAL_STATE.filters[1] = ", WIDGET_INITIAL_STATE.filters[1]);
.as-console-wrapper {
max-height: 100% !important;
}