You need to enable JavaScript to run this app. Google App Script三类Scriptlet的使用差异与选型指南
优惠活动
大模型
产品
解决方案
定价
更多

Google App Script三类Scriptlet的使用差异与选型指南

Google Apps Script HTML 模板三类Scriptlet的落地差异与选型指南

Google Apps Script 的HTML模板引擎提供的三类Scriptlet没有复杂的抽象概念,核心差异完全围绕「输出行为」和「转义规则」两个维度,结合实际开发场景的选型逻辑可以直接对照落地,没有模糊的适用边界。


1. 标准Scriptlet <? ... ?>

核心特性

无任何HTML输出:执行块内的服务端JavaScript代码后,不会把任何执行结果、代码内容注入到最终渲染的HTML页面中。因为不输出内容,自然不存在内容转义的逻辑。

适用场景

所有不需要直接渲染到页面上的服务端逻辑都应该用这个语法,是所有数据处理、逻辑判断环节的唯一选项。

代码示例

<?
  // 直接从工作表读取源数据,不需要把查询代码输出到页面
  const sheetData = SpreadsheetApp.getActive()
    .getSheetByName("用户列表")
    .getDataRange()
    .getValues();
  
  // 做数据清洗和格式预处理,纯逻辑计算,无输出
  const validUserList = sheetData
    .filter(row => row[1] === "已激活") // 过滤未激活用户
    .map(row => ({
      userId: row[0],
      userName: row[2].trim()
    }));

  // 根据当前用户权限判断是否显示管理员入口
  const isAdmin = Session.getActiveUser().getEmail() === "admin@example.com";
?>

避坑提示

不要把需要展示的内容写在这类Scriptlet块里,否则内容会只在服务端执行阶段存在,最终渲染的页面上完全看不到。


2. 打印Scriptlet <?= ... ?>

核心特性

执行块内的代码后,会把计算结果自动注入到HTML的对应位置,同时自动启用上下文感知的内容转义——引擎会根据这段代码在HTML中所处的位置(是在文本节点、标签属性、<script>脚本块、还是<style>样式块),自动匹配对应的转义规则,把可能导致代码注入的特殊字符转成对应的HTML实体,从根源上防范XSS安全问题。

适用场景

这是所有动态内容渲染的默认首选,只要是需要把动态变量、计算结果展示到页面上,且内容来源是不可信的(比如用户输入、数据库存储的文本、第三方接口返回的内容),都应该用这个语法,不需要手动做转义处理。

代码示例

<!-- 把前面预处理好的用户列表渲染成页面内容 -->
<div class="user-panel">
  <? if (isAdmin) { ?>
    <h3>管理员视图:激活用户列表</h3>
  <? } else { ?>
    <h3>普通用户视图:</h3>
  <? } ?>
  <ul class="user-list">
    <? for (let i = 0; i < validUserList.length; i++) { ?>
      <li>
        <!-- 自动转义:如果userName里包含 <img src=x onerror=alert(1)> 这类恶意代码,会被转成纯文本展示,不会触发脚本执行 -->
        用户ID:<?= validUserList[i].userId ?>,用户名:<?= validUserList[i].userName ?>
      </li>
    <? } ?>
  </ul>
</div>

<script>
  // 给前端JS传用户列表数据,引擎会自动把字符串里的单引号、反斜杠做转义,避免JS语法错误
  const pageUserData = <?= validUserList ?>;
</script>

避坑提示

不要用这个语法输出已经构建好的完整HTML片段,否则所有<p>、<strong>这类HTML标签都会被转成纯文本字符,页面会显示成满屏的标签代码,而不是正常渲染的内容。


3. 强制打印Scriptlet <?!= ... ?>

核心特性

执行块内的代码后,会把计算结果原封不动注入到HTML对应位置,完全不做任何内容转义,所有特殊字符、HTML标签、脚本内容都会被原样保留。

适用场景

仅在明确确认渲染内容完全可信、且内容本身就是合法HTML结构的时候使用——典型场景包括:服务端生成的、经过全量XSS清洗的富文本内容、已经通过白名单校验的HTML组件片段、固定结构的静态HTML代码。

代码示例

<?
  // 对用户提交的富文本做全量安全清洗:移除所有script标签、事件属性,仅保留白名单内的合法标签
  const cleanedRichContent = doSanitizeRichHtml(userSubmittedContent);
?>
<div class="rich-content-container">
  <!-- 不做转义,直接输出已经清洗完成的合法HTML,保留<p>、<strong>这类合法标签的结构 -->
  用户发布的富文本:<?!= cleanedRichContent ?>
</div>

避坑提示

严禁用这个语法直接输出未做安全处理的用户输入、第三方未校验的接口内容,否则恶意脚本会被直接注入到页面中,产生严重的XSS安全漏洞。


三类Scriptlet选型对照速查

  • 标准Scriptlet <? ... ?>:只跑逻辑,不输出内容,所有数据查询、变量定义、循环判断环节用这个
  • 打印Scriptlet <?= ... ?>:默认渲染所有动态内容,自动转义防注入,除非明确不需要转义否则优先用这个
  • 强制打印Scriptlet <?!= ... ?>:仅用来输出经过安全校验的合法HTML片段,不做任何转义

补充说明:很多开发者调试时会在标准Scriptlet块里写console.log(xxx),这类代码会正常在Apps Script的执行日志中输出,也不会污染最终渲染的HTML,属于标准Scriptlet的合理使用范围。

内容的提问来源于stack exchange,提问作者aerioeus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.31 07:06:08